我正在尝试使用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 作为 Popenexecutable
参数的参数。仅仅powershell.exe
可能还不够。要找到powershell
的真正绝对路径,请执行where.exe powershell
。然后你可以把它传递给Popen。请注意,shell
仍然是正确的。它将使用默认的外壳,但将命令传递给powershell.exe
powershell = C:WindowsSystem32WindowsPowerShellv1.0powershell.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
环境变量确定要调用的shell,该变量仍然指向cmd.exe
,即使在最新的W10更新中,就GUI提供的默认shell而言,它已转向PowerShell。
对于向后兼容性,这不会很快改变,而且可能永远不会改变。
因此,您的选择是:
-
使用
cmd
语法,如莫里斯·迈耶的回答中所建议的那样。 -
不要使用
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
,因为一旦PowerShellCore发布,该命令也有可能在Unix平台上工作。
仅限Windows:在重新定义环境变量COMSPEC
首先指向PowerShell之后,使用shell = True
的示例:
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开始,默认情况下,仅使用
-c
调用powershell
(解释为-Command
)仍会加载配置文件,这可能会产生意想不到的副作用(通过显式调用上面使用的powershell
,-noprofile
抑制)。- 将默认行为更改为不加载配置文件是此GitHub问题的主题,目的是使PowerShell的CLI与类似POSIX的shell保持一致。
您可以使用"&"字符而不是分号连接多个命令。试试这个:
pg = subprocess.Popen("cd c:/mydirectory & ./runExecutable.exe --help", stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=True)
buff,buffErr = pg.communicate()