在python脚本中运行powershell脚本,如何让python在运行时打印powershell输出

use*_*276 9 python windows powershell stdout python-2.7

我正在编写一个python脚本,它检查各种条件并相应地运行一个PowerShell脚本,以帮助我自动从Windows XP迁移到Windows 7. powershell脚本提供自己的输出,为用户提供有关正在发生的事情的更新.我想获取powershell脚本的输出并将其打印为python脚本的输出.我已经环顾了一些似乎想要做同样事情的问题,但它们似乎并不适合我.最初我尝试过使用

import subprocess
subprocess.call(["C:\Users\gu2124\Desktop\helloworld.ps1"])
Run Code Online (Sandbox Code Playgroud)

正如在这里建议的那样,从Python脚本运行PowerShell函数,但我发现这等待程序首先执行而不提供输出所以我发现我需要使用subprocess.Popen()这里所谓的使用 Popen 在Python中执行Powershell脚本,如何获取Powershell脚本的输出并将其更新到网页?所以我试过这个

import subprocess
subprocess.Popen(["C:\Users\gu2124\Desktop\helloworld.ps1"], stdout=sys.stdout)
Run Code Online (Sandbox Code Playgroud)

我收到这个错误

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'
Run Code Online (Sandbox Code Playgroud)

我不完全确定这意味着什么,但是从我认为我理解后读取这个AttributeError:StringIO实例没有属性'fileno'是因为我错误地搞乱了stdout.我看了很多,我发现这为什么我的python子进程代码不起作用?答案说要使用,stdout=subprocess.PIPE所以我尝试了这个

import subprocess
subprocess.Popen(["C:\Users\gu2124\Desktop\helloworld.ps1"], stdout=subprocess.PIPE)
Run Code Online (Sandbox Code Playgroud)

这也没有给我输出最后我看到这个http://www.pythonforbeginners.com/os/subprocess-for-system-administrators并将我的代码更改为此

import subprocess
p = subprocess.Popen(["powershell","C:\Users\gu2124\Desktop\helloworld.ps1"], stdout=subprocess.PIPE)
print p.communicate
Run Code Online (Sandbox Code Playgroud)

我认为这可能是因为我最初尝试从命令行运行PowerShell脚本,所以我必须首先打开PowerShell.当我直接在命令行中输入这些命令时,它按照应该的方式工作,但是当我通过python脚本运行它时,它会给出这个

<bound method Popen.communicate of <subprocess.Popen object at 0x00000000026E4A90>>
Run Code Online (Sandbox Code Playgroud)

这是一个改进我猜,但不是我期待的"你好世界".我不知道接下来我应该尝试做些什么.任何帮助将不胜感激

此外,如果我在这里使用的powershell脚本是必需的

$strString = "Hello World"
write-host $strString

function ftest{
$test = "Test"
write-host $test
}
Run Code Online (Sandbox Code Playgroud)

编辑:我尝试升级到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 
Run Code Online (Sandbox Code Playgroud)

Nuc*_*eon 16

  1. 确保您可以运行powershell脚本(默认情况下禁用).你可能已经这样做了.http://technet.microsoft.com/en-us/library/ee176949.aspx

    Set-ExecutionPolicy RemoteSigned
    
    Run Code Online (Sandbox Code Playgroud)
  2. 在您的powershell脚本上运行此python脚本helloworld.py:

    # -*- coding: iso-8859-1 -*-
    import subprocess, sys
    
    p = subprocess.Popen(["powershell.exe", 
                  "C:\\Users\\USER\\Desktop\\helloworld.ps1"], 
                  stdout=sys.stdout)
    p.communicate()
    
    Run Code Online (Sandbox Code Playgroud)

此代码基于python3.4(或任何3.x系列解释器),但它也适用于python2.x系列.

C:\Users\MacEwin\Desktop>python helloworld.py
Hello World
Run Code Online (Sandbox Code Playgroud)

  • 这里棘手的部分对于非 PS 和 Py 专家来说一点也不明显,那就是如果您有许多 powershell 命令行参数(或非常长/复杂的单行代码),您**必须**调用 shell使用数组,其中每个项目都是一个单独的参数。否则,您可能会浪费大量时间来尝试调试为什么输出不是您所期望的。 (8认同)

Ste*_*fan 6

除了前面的答案之外,我还有一些建议可以使您的代码更加可移植。

您可以使用它仅为 Python 脚本创建的 PowerShell 实例设置它,而不是全局设置(这会带来一些安全问题)ExecutionPolicyRemoteSigned

import subprocess, sys    
p = subprocess.Popen('powershell.exe -ExecutionPolicy RemoteSigned -file "hello world.ps1"', stdout=sys.stdout)
p.communicate()
Run Code Online (Sandbox Code Playgroud)

请注意允许 PowerShell 脚本的路径/文件名包含空格的引号。

此外,如上面的示例所示,您可以使用相对路径来调用 PowerShell 脚本。该路径相对于您的 Python 工作区目录。


Ans*_*ers 5

我没有安装 Python 2.7,但在 Python 3.3 中Popen使用stdoutset调用可以正常sys.stdout工作。不过,在我逃脱路径中的反斜杠之前。

>>> import subprocess
>>> import sys
>>> p = subprocess.Popen(['powershell.exe', 'C:\\Temp\\test.ps1'], stdout=sys.stdout)
>>> Hello World
_
Run Code Online (Sandbox Code Playgroud)