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

问题描述 投票:0回答:5

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

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

正如这里建议的那样 从Python脚本运行PowerShell函数,但我发现这会等待程序首先执行并且不会给出输出,所以我发现我需要使用

subprocess.Popen()
,正如这里建议的那样使用Popen在Python中执行Powershell脚本,如何获取Powershell脚本的输出并将其更新到网页?所以我尝试了这个

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'

我不完全确定这意味着什么,但从我认为读完此内容后我理解的内容来看,AttributeError: StringIO 实例没有属性“fileno”是因为我错误地弄乱了标准输出。我环顾四周,发现了这个为什么我的 python 子进程代码不起作用?答案说要使用

stdout=subprocess.PIPE
所以我尝试了这个

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

这也没有给我输出 最后我看到了这个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

我认为这可能是因为我最初尝试从命令行运行 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 
python windows python-2.7 powershell stdout
5个回答
66
投票
  1. 确保您可以运行powershell脚本(默认情况下禁用)。可能您已经这样做了。 http://technet.microsoft.com/en-us/library/ee176949.aspx

    Set-ExecutionPolicy RemoteSigned
    
  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()
    

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

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

7
投票

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

您可以使用它仅为由 Python 脚本创建的 PowerShell 实例设置它,而不是将

ExecutionPolicy
全局设置为
RemoteSigned
(这会带来一些安全问题):

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

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

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


6
投票

我没有安装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
投票

这就是我从 Popen 获取输出的方式

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

print(p_out)

来自 Popen.communicate() 的文档。该函数返回一个元组 (stdout_data, stderr_data)。


0
投票

在这里,我创建了自己的函数来运行任何带参数的 powershell 脚本

import subprocess  # IMPORT FOR SUB PROCESS . RUN METHOD

POWERSHELL_PATH = "powershell.exe"  # POWERSHELL EXE PATH
ps_script_path = "C:\\PowershellScripts\\FTP_UPLOAD.PS1"  # YOUR POWERSHELL FILE PATH


class Utility:  # SHARED CLASS TO USE IN OUR PROJECT

    @staticmethod    # STATIC METHOD DEFINITION
    def run_ftp_upload_powershell_script(script_path, *params):  # SCRIPT PATH = POWERSHELL SCRIPT PATH,  PARAM = POWERSHELL SCRIPT PARAMETERS ( IF ANY )

        commandline_options = [POWERSHELL_PATH, '-ExecutionPolicy', 'Unrestricted', script_path]  # ADD POWERSHELL EXE AND EXECUTION POLICY TO COMMAND VARIABLE
        for param in params:  # LOOP FOR EACH PARAMETER FROM ARRAY
            commandline_options.append("'" + param + "'")  # APPEND YOUR FOR POWERSHELL SCRIPT

        process_result = subprocess.run(commandline_options, stdout = subprocess.PIPE, stderr = subprocess.PIPE, universal_newlines = True)  # CALL PROCESS

        print(process_result.returncode)  # PRINT RETURN CODE OF PROCESS  0 = SUCCESS, NON-ZERO = FAIL  
        print(process_result.stdout)      # PRINT STANDARD OUTPUT FROM POWERSHELL
        print(process_result.stderr)      # PRINT STANDARD ERROR FROM POWERSHELL ( IF ANY OTHERWISE ITS NULL|NONE )

        if process_result.returncode == 0:  # COMPARING RESULT
            Message = "Success !"
        else:
            Message = "Error Occurred !"

        return Message  # RETURN MESSAGE
© www.soinside.com 2019 - 2024. All rights reserved.