Python Popen在复合命令(PowerShell)中失败

我正在尝试使用Python的Popen更改工作目录并执行命令.

pg = subprocess.Popen("cd c:/mydirectory ; ./runExecutable.exe --help", stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=True)
buff,buffErr = pg.communicate()

但是,powershell返回“系统找不到指定的路径”.该路径确实存在.

如果我跑步

 pg = subprocess.Popen("cd c:/mydirectory ;", stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=True)

它返回相同的东西.

但是,如果我运行此命令:(无分号)

pg = subprocess.Popen("cd c:/mydirectory",stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=True)

该命令返回无错误.这使我相信分号是有问题的.这种现象的原因是什么,我该如何解决?

我知道我可以执行c:/mydirectory/runExecutable.exe –help,但我想知道为什么会这样.

更新:

我已经测试过将路径传递到powershell作为Popen可执行参数的参数.仅powershell.exe可能还不够.要找到powershell的真实绝对路径,请执行where.exe powershell.然后,您可以将其传递给Popen.请注意,shell仍然是正确的.它将使用默认外壳程序,但将命令传递给powershell.exe

powershell = C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe
pg = subprocess.Popen("cd c:/mydirectory ; ./runExecutable.exe", stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=True, executable=powershell)
buff,buffErr = pg.communicate()
//It works!

解决方法:

在您的subprocess.Popen()调用中,shell = True表示应使用平台的默认Shell.

尽管Windows世界正从CMD(cmd.exe)迁移到PowerShell,但值得称赞的是,Python根据COMSPEC环境变量来确定要调用的外壳程序,该环境变量仍然指向cmd.exe,即使在朝WMD的最新W10更新中在GUI提供的默认外壳程序方面使用PowerShell.

为了向后兼容,这不会很快改变,并且可能永远不会改变.

因此,您的选择是:

>使用cmd语法,如Maurice Meyer’s答案中所建议.
>不要使用shell = True并显式调用powershell.exe-参见下文.
>仅限Windows:在使用shell = True之前重新定义环境变量COMSPEC-参见下文.

一个简单的Python示例,说明如何直接调用powershell二进制文件,并通过命令行开关后跟一个包含PowerShell源代码的单个字符串来执行:

import subprocess

args = 'powershell', '-noprofile', '-command', 'set-location /; $pwd'
subprocess.Popen(args)

请注意,我故意使用powershell而不是powershell.exe,因为一旦PowerShell Core发布,这也打开了该命令也可以在Unix平台上运行的可能性.

仅限Windows:在重新定义环境变量COMSPEC以首先指向PowerShell之后,shell = True的示例:

import os, subprocess    

os.environ["COMSPEC"] = 'powershell'

subprocess.Popen('Set-Location /; $pwd', shell=True)

注意:

>仅在Windows上使用COMSPEC.在Unix平台上,shell可执行文件始终为/ bin / sh
>从Windows PowerShell v5.1 / PowerShell Core v6-beta.3开始,仅使用-c(解释为-Command)调用powershell仍会默认加载配置文件,这可能会带来意外的副作用(显式调用powershell上面使用的-noprofile禁止这样做.

>将默认行为更改为不加载配置文件是此GitHub issue的主题,目的是使PowerShell的CLI与类似POSIX的shell的CLI保持一致.

上一篇:python-尝试后,sys.exit无法按预期工作:


下一篇:python子进程终端mac osx