我正在编写一个python脚本,它检查各种条件并相应地运行一个PowerShell脚本,以帮助我自动从Windows XP迁移到Windows 7. powershell脚本提供自己的输出,为用户提供有关正在发生的事情的更新。我想获取powershell脚本的输出并将其打印为python脚本的输出。我已经环顾了一些似乎想要做同样事情的问题,但它们似乎并不适合我。最初我尝试使用
import subprocess
subprocess.call(["C:\Users\gu2124\Desktop\helloworld.ps1"])
正如在此Run PowerShell function from Python script所建议的那样,但我发现这等待程序首先执行并且不提供输出所以我发现我需要使用subprocess.Popen()
,因为这里有所谓{{3}所以我试过这个
import subprocess
subprocess.Popen(["C:\Users\gu2124\Desktop\helloworld.ps1"], stdout=sys.stdout)
我收到此错误
Traceback (most recent call last):
File "C:\Users\gu2124\Desktop\pstest.py", line 5, in <module>
subprocess.Popen(["C:\Users\gu2124\Desktop\helloworld.py1"], stdout=sys.stdout)
File "C:\Python27\lib\subprocess.py", line 701, in __init__
errread, errwrite), to_close = self._get_handles(stdin, stdout, stderr)
File "C:\Python27\lib\subprocess.py", line 848, in _get_handles
c2pwrite = msvcrt.get_osfhandle(stdout.fileno())
File "<string>", line 523, in __getattr__
File "C:\Program Files\PyScripter\Lib\rpyc.zip\rpyc\core\netref.py", line 150, in __getattr__
return syncreq(self, consts.HANDLE_GETATTR, name)
File "C:\Program Files\PyScripter\Lib\rpyc.zip\rpyc\core\netref.py", line 71, in syncreq
return conn.sync_request(handler, oid, *args)
File "C:\Program Files\PyScripter\Lib\rpyc.zip\rpyc\core\protocol.py", line 434, in sync_request
raise obj
AttributeError: DebugOutput instance has no attribute 'fileno'
我不完全确定这意味着什么,但是从我认为我理解后阅读Use Popen to execute a Powershell script in Python, how can I get the Powershell script's output and update it to web page?之后我知道这是因为我错误地弄乱了标准输出。我看了很多,我发现这个AttributeError: StringIO instance has no attribute 'fileno'答案说使用stdout=subprocess.PIPE
,所以我尝试了这个
import subprocess
subprocess.Popen(["C:\Users\gu2124\Desktop\helloworld.ps1"], stdout=subprocess.PIPE)
这也不给我输出 最后我看到了这个Why won't my python subprocess code work?并将我的代码更改为此
import subprocess
p = subprocess.Popen(["powershell","C:\Users\gu2124\Desktop\helloworld.ps1"], stdout=subprocess.PIPE)
print p.communicate
我认为可能是因为我最初尝试从命令行运行PowerShell脚本,所以我必须首先打开PowerShell。当我直接在命令行中输入这些命令时,它按照应该的方式工作,但是当我通过python脚本运行它时,它会给出这个
<bound method Popen.communicate of <subprocess.Popen object at 0x00000000026E4A90>>
这是一个改进我想但不是我期待的“Hello world”。 我不知道接下来我应该尝试做些什么。任何帮助将不胜感激
此外,如果我在这里使用的powershell脚本是
$strString = "Hello World"
write-host $strString
function ftest{
$test = "Test"
write-host $test
}
编辑:我尝试升级到python 3.3,就像在第一个答案中提到的那样,但我仍然无法让它工作。我使用了命令p = subprocess.Popen(['powershell.exe', "C:\\Users\\gu2124\\Desktop\\helloworld.ps1"], stdout=sys.stdout)
并且确定该文件存在,但我收到此错误:
Traceback (most recent call last):
File "<pyshell#3>", line 1, in <module>
p = subprocess.Popen(['powershell.exe', "C:\\Users\\gu2124\\Desktop\\helloworld.ps1"], stdout=sys.stdout)
File "C:\Python27\lib\subprocess.py", line 701, in __init__
errread, errwrite), to_close = self._get_handles(stdin, stdout, stderr)
File "C:\Python27\lib\subprocess.py", line 848, in _get_handles
c2pwrite = msvcrt.get_osfhandle(stdout.fileno())
UnsupportedOperation: fileno
答案 0 :(得分:14)
确保您可以运行powershell脚本(默认情况下已禁用)。你可能已经这样做了。 http://technet.microsoft.com/en-us/library/ee176949.aspx
Set-ExecutionPolicy RemoteSigned
在您的powershell脚本helloworld.py
上运行此python脚本:
# -*- coding: iso-8859-1 -*-
import subprocess, sys
p = subprocess.Popen(["powershell.exe",
"C:\\Users\\USER\\Desktop\\helloworld.ps1"],
stdout=sys.stdout)
p.communicate()
此代码基于python3.4(或任何3.x系列解释器),但它也适用于python2.x系列。
C:\Users\MacEwin\Desktop>python helloworld.py
Hello World
答案 1 :(得分:1)
我没有安装Python 2.7,但是在Python 3.3中调用Popen
并将stdout
设置为sys.stdout
工作得很好。然而,在我逃离路径中的反斜杠之前不是。
>>> import subprocess
>>> import sys
>>> p = subprocess.Popen(['powershell.exe', 'C:\\Temp\\test.ps1'], stdout=sys.stdout)
>>> Hello World
_
答案 2 :(得分:0)
除了前面的答案之外,我还有一些建议可以让您的代码更具可移植性。
不是将 ExecutionPolicy
全局设置为 RemoteSigned
(这会带来一些安全问题),您可以使用它来仅为您的 Python 脚本创建的 PowerShell 实例设置它:
import subprocess, sys
p = subprocess.Popen('powershell.exe -ExecutionPolicy RemoteSigned -file "hello world.ps1"', stdout=sys.stdout)
p.communicate()
注意允许 PowerShell 脚本的路径/文件名包含空格的引号。
此外,如上例所示,您可以使用相对路径来调用您的 PowerShell 脚本。该路径相对于您的 Python 工作区目录。