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

时间:2017-07-13 20:46:34

标签: python powershell subprocess popen

我正在尝试使用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 executable参数的参数传递。仅powershell.exe可能还不够。要查找powershell的真实绝对路径,请执行where.exe powershell。然后你可以将它传递给Popen。请注意shell仍然是正确的。它将使用默认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!

2 个答案:

答案 0 :(得分:4)

subprocess.Popen()来电中,shell=True表示应该使用平台的默认 shell。

虽然Windows世界 - 值得称赞 - 从CMD(cmd.exe)迁移到PowerShell,但 Python根据COMSPEC环境变量确定要调用的shell,< strong>仍然指向cmd.exe ,即使在最新的W10更新中,就 GUI 提供的默认shell而言,已经转向PowerShell。

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

因此,选项是:

  • 根据Maurice Meyer's回答中的建议使用cmd语法。

  • 使用shell = True并明确调用powershell.exe - 请参阅下文。

  • 仅限Windows :在使用COMSPEC之前重新定义环境变量shell = True - 请参阅下文。

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

import subprocess

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

请注意,我故意使用powershell而不是powershell.exe,因为这样就可以让命令在 Unix 平台上运行,{{3} }被释放。

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

import os, subprocess    

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

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

注意:

  • COMSPEC仅在 Windows 上查阅;在Unix平台上,shell可执行文件总是 /bin/sh

  • 从Windows PowerShell v5.1 / PowerShell Core v6-beta.3开始,仅使用powershell(解释为-c)调用-Command仍会加载配置文件< em>默认情况下,可能会产生意外的副作用(上面使用powershell的显式调用,-noprofile会抑制)。

    • 将默认行为更改为而不是加载配置文件是此PowerShell Core的主题,以便将PowerShell的CLI与类似POSIX的shell对齐。

答案 1 :(得分:0)

您可以使用'&amp;'连接多个命令字符而不是分号。试试这个:

{{1}}