【问题标题】:Passing variables between Powershell commands in a python script在 Python 脚本中的 Powershell 命令之间传递变量
【发布时间】:2014-11-19 20:16:29
【问题描述】:

我必须通过 python 脚本调用两个 powershell 命令。我目前正在为此使用 subprocess.Popen。

第一个命令返回一个 powershell 对象。示例:

PS>$temp = <powershell_command_1>

$temp 对象中有多个属性。必须将整个对象传递给同一脚本中的第二个 powershell 对象。例如。

PS><powershell_command_2> -object $temp

如果 $temp 是一个字符串,我在传递 python 字符串变量时没有问题。但是,在这种情况下 $temp 是一个对象。如何将此值传递给第二个 PS cmdlet?

这是回溯

Traceback (most recent call last):
  File "file.py", line 430, in <module>
    status = c1.configure_cluster()
  File "file.py", line 319, in configure_cluster
    configure_cluster = subprocess.Popen([self.powershell_binary,'-ExecutionPolicy','ByPass',r'Cmdlet2', temp], stdout=subprocess.PIPE)
  File "C:\Python34\lib\subprocess.py", line 858, in __init__
    restore_signals, start_new_session)
  File "C:\Python34\lib\subprocess.py", line 1085, in _execute_child
    args = list2cmdline(args)
  File "C:\Python34\lib\subprocess.py", line 663, in list2cmdline
    needquote = (" " in arg) or ("\t" in arg) or not arg
TypeError: Type str doesn't support the buffer API

【问题讨论】:

  • 你看过Invoke-Command cmdlet吗?
  • 这两个powershell命令是分开运行还是同时运行?例如Powershell -command { command_1 | command_2 } 如果第二个命令接受管道,或者 Powershell -command { command_2 -object (command_1) } 如果不接受。
  • 它们必须单独运行。 python 脚本调用 cmdlet 1,然后根据输出变量的值进行其他处理,随后必须调用 cmdlet 2,其值为 $temp。
  • 想到两件事:使用Export-CliXml/Import-CliXml 来持久化对象;或 Powershell 远程会话应该是持久的,因此您可以创建会话,使其保持运行,并使用 Invoke-Command 向其发送更多命令。

标签: python powershell


【解决方案1】:

如果这两个命令可以一起运行,那么就一起运行它们,但是正如你所说的你必须分别运行它们,你可以尝试使用Export-Clixml 将对象保存到文件然后Import-Clixml 重新加载它。这是一个工作示例:

#!/usr/bin/env python3
import base64, subprocess, sys

def powershell(cmd, input=None):
    cmd64 = base64.encodebytes(cmd.encode('utf-16-le')).decode('ascii').strip()
    stdin = None if input is None else subprocess.PIPE
    process = subprocess.Popen(["powershell.exe", "-NonInteractive", "-EncodedCommand", cmd64], stdin=stdin, stdout=subprocess.PIPE)
    if input is not None:
        input = input.encode(sys.stdout.encoding)
    output, stderr = process.communicate(input)
    output = output.decode(sys.stdout.encoding).replace('\r\n', '\n')
    return output

command=r"""
$data = Get-ChildItem C:\Python34
$data | Export-Clixml -Path c:\temp\state.xml
$data
"""
output = powershell(command)
print(output)
print("Do some processing here...")
result = """NEWS.txt=1
README.txt=1
\u00a3.txt=1
"""
command = r"""
$in = $input|Out-String
$selected = $in | ConvertFrom-StringData
$data = Import-Clixml -Path c:\\temp\\state.xml
$data |? { $selected.ContainsKey($_.Name) } | Select Length,FullName
"""
output = powershell(command, result)
print(output)

它给出以下输出:

C:\Temp>py state.py


    Directory: C:\Python34


Mode                LastWriteTime     Length Name
----                -------------     ------ ----
d----        24/10/2014     11:52            DLLs
d----        24/10/2014     11:52            Doc
d----        24/10/2014     11:52            include
d----        24/10/2014     11:52            Lib
d----        24/10/2014     11:52            libs
d----        05/11/2014     16:53            Scripts
d----        24/10/2014     11:52            tcl
d----        24/10/2014     11:52            Tools
-a---        06/10/2014     22:19      31073 LICENSE.txt
-a---        21/09/2014     21:03     367504 NEWS.txt
-a---        06/10/2014     22:15      27136 python.exe
-a---        06/10/2014     22:15      27648 pythonw.exe
-a---        06/10/2014     22:10       6942 README.txt
-a---        19/11/2014     11:59          5 £.txt



Do some processing here...

                                 Length FullName
                                 ------ --------
                                 367504 C:\Python34\NEWS.txt
                                   6942 C:\Python34\README.txt
                                      5 C:\Python34\£.txt

您当然可以将 XML 加载到 Python 中并对其进行操作,在这种情况下使用 ConvertTo-Xml -as string 而不是 Export-CliXml 尽管我不太确定如何将其转换回 Powershell 对象而不是 xml 对象。 (编辑:Powershell's import-clixml from string 涵盖通过 Clixml 的往返对象而不使用文件)。

【讨论】:

  • 谢谢,我采用了您的部分解决方案来解决我的问题。我使用了:command = r""" .... """ 并重新排列了我的一些代码,以摆脱中间处理。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-05-01
  • 2021-08-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-10-26
相关资源
最近更新 更多