简体   繁体   English

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

[英]Running powershell script within python script, how to make python print the powershell output while it is running

I am writing a python script which checks various conditions and runs a powershell script accordingly to help me automate migration from windows XP to windows 7. The powershell script gives its own output giving the user updates as to what is happening.我正在编写一个 python 脚本,它检查各种条件并相应地运行一个 powershell 脚本,以帮助我自动从 windows XP 迁移到 windows 7。powershell 脚本提供自己的输出,让用户更新正在发生的事情。 I would like to take the output of the powershell script and print it as output of the python script.我想获取 powershell 脚本的输出并将其打印为 python 脚本的输出。 I have looked around at some questions which seem to want to do the same thing but they don't seem to be working for me.我环顾了一些似乎想做同样事情的问题,但它们似乎对我不起作用。 Initially I tried using最初我尝试使用

import subprocess
subprocess.call(["C:\Users\gu2124\Desktop\helloworld.ps1"])

As was suggested here Run PowerShell function from Python script but I found out that this waits for the program to execute first and does not give output so I found out I need to use subprocess.Popen() as was suggusted here Use Popen to execute a Powershell script in Python, how can I get the Powershell script's output and update it to web page?正如这里所建议的从 Python 脚本运行 PowerShell 函数,但我发现这会等待程序首先执行并且不提供输出,所以我发现我需要使用 subprocess.Popen subprocess.Popen()建议这里使用 Popen 执行Python 中的 Powershell 脚本,如何获取 Powershell 脚本的输出并将其更新到网页? so I tried this所以我尝试了这个

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

and I get this error我得到这个错误

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'

I'm not completely sure what this means but from what I think I understand after reading this AttributeError: StringIO instance has no attribute 'fileno' is that it is because I am messing with the stdout incorrectly.我不完全确定这意味着什么,但从我阅读此AttributeError: StringIO instance has no attribute 'fileno'后的理解来看,这是因为我错误地弄乱了标准输出。 I looked a around more and I found this Why won't my python subprocess code work?我环顾四周,发现为什么我的 python 子进程代码不起作用? where the answers said to use stdout=subprocess.PIPE so I tried this答案说使用stdout=subprocess.PIPE所以我尝试了这个

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

which also does not give me output Finally I saw this http://www.pythonforbeginners.com/os/subprocess-for-system-administrators and changed my code to this这也没有给我输出最后我看到了这个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

I thought that it may because I am initially trying to run a powershell script from the command line so I have to open powershell first.我认为这可能是因为我最初试图从命令行运行 powershell 脚本,所以我必须先打开 powershell。 When I type these commands directly into the command line it works the way it should but when I run it through the python script it gives this当我直接在命令行中输入这些命令时,它会以应有的方式工作,但是当我通过 python 脚本运行它时,它会给出这个

<bound method Popen.communicate of <subprocess.Popen object at 0x00000000026E4A90>>

which is an improvement I guess but not the "Hello world" I was expecting.我猜这是一个改进,但不是我期待的“Hello world”。 I have no idea what I should try to do next to get this to work.我不知道接下来我应该怎么做才能让它发挥作用。 Any help would be greatly appreciated任何帮助将不胜感激

Also if the powershell script I am using is needed here it is此外,如果这里需要我使用的 powershell 脚本,那就是

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

function ftest{
$test = "Test"
write-host $test
}

EDIT: I tried upgrading to python 3.3 like was suggested in the first answer but I still can't get it to work.编辑:我尝试像第一个答案中建议的那样升级到 python 3.3,但我仍然无法让它工作。 I used the command p = subprocess.Popen(['powershell.exe', "C:\\Users\\gu2124\\Desktop\\helloworld.ps1"], stdout=sys.stdout) and am sure the file is there but am getting this error:我使用了命令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 
  1. Make sure you can run powershell scripts (it is disabled by default).确保您可以运行 powershell 脚本(默认情况下禁用)。 Likely you have already done this.您可能已经这样做了。 http://technet.microsoft.com/en-us/library/ee176949.aspx http://technet.microsoft.com/en-us/library/ee176949.aspx

     Set-ExecutionPolicy RemoteSigned
  2. Run this python script on your powershell script helloworld.py :在你的 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()

This code is based on python3.4 (or any 3.x series interpreter), though it should work on python2.x series as well.此代码基于 python3.4(或任何 3.x 系列解释器),但它也应该适用于 python2.x 系列。

C:\Users\MacEwin\Desktop>python helloworld.py
Hello World

I don't have Python 2.7 installed, but in Python 3.3 calling Popen with stdout set to sys.stdout worked just fine.我没有安装 Python 2.7,但在 Python 3.3 中调用Popen并将stdout设置为sys.stdout工作得很好。 Not before I had escaped the backslashes in the path, though.不过,在我逃脱了路径中的反斜杠之前。

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

In addition to the previous answers, I have some suggestions which makes your code more portable.除了前面的答案之外,我还有一些建议可以使您的代码更具可移植性。

Instead of setting ExecutionPolicy globally to RemoteSigned (which imposes some security issues) you can use this to set it only for the PowerShell instance created by your Python script:除了将ExecutionPolicy全局设置为RemoteSigned (这会带来一些安全问题),您可以使用它来仅为 Python 脚本创建的 PowerShell 实例设置它:

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

Note the quotes which allows your PowerShell-script's path/filename to contain spaces.请注意允许 PowerShell 脚本的路径/文件名包含空格的引号。

Furthermore, as shown in the above example, you can use a relative path to call your PowerShell script.此外,如上例所示,您可以使用相对路径来调用您的 PowerShell 脚本。 The path is relative to your Python workspace directory.该路径相对于您的 Python 工作区目录。

This is how I get the output from Popen这就是我从 Popen 获取输出的方式

p = subprocess.Popen(["powershell","C:\Users\gu2124\Desktop\helloworld.ps1"], stdout=subprocess.PIPE)
p_out, p_err = p.communicate()

print(p_out)

From the docs on Popen.communicate().来自 Popen.communicate() 上的文档。 The function returns a tuple (stdout_data, stderr_data).该函数返回一个元组(stdout_data,stderr_data)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM