I have to invoke two powershell commands via a python script. I am currently using subprocess.Popen for this.
The first command returns a powershell object. Example:
PS>$temp = <powershell_command_1>
The $temp object has multiple properties in it. The entire object has to be passed to a second powershell object in the same script. eg.
PS><powershell_command_2> -object $temp
If $temp were to be a string, I have no problems with passing the python string variable. However, in this case $temp is an object. How can I pass this value to the second PS cmdlet?
Here is the traceback
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
If the two commands can be run together then just run them together, but as you say you have to run them separately you could try using Export-Clixml
to save the object to a file then Import-Clixml
to reload it. Here's a working example:
#!/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)
Which gives the following 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
You could of course load the XML into Python and manipulate it, in which case use ConvertTo-Xml -as string
rather than Export-CliXml
though I'm not quite sure how you get that converted back to Powershell objects rather than an xml object. (Edit: Powershell's import-clixml from string covers round-tripping objects through Clixml without using a file).
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.