Python 的 subprocess.Popen 是不是接受路径中的空格?
Posted
技术标签:
【中文标题】Python 的 subprocess.Popen 是不是接受路径中的空格?【英文标题】:Does Python's subprocess.Popen accept spaces in paths?Python 的 subprocess.Popen 是否接受路径中的空格? 【发布时间】:2014-09-03 23:31:53 【问题描述】:我有一个简单的 Python 脚本:
log("Running command: " + str(cmd))
process = subprocess.Popen(
cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE,
stdin=subprocess.PIPE, close_fds=close_fds)
我在 Windows 上的相同 python 版本 2.6.1 上执行它,但在不同的虚拟机上。一个是 Windows Server 2008 Enterprise,第二个是 Windows Server Enterprise,我在 only 其中一个上遇到错误。
来自 Windows Server Enterprise 的日志:
Running command: C:\Program File\MyProgram\program.exe "parameters"
Error: 'C:\\Program' is not recognized as an internal or external command
来自 Windows Server 2008 Enterprise 的日志:
Running command: C:\Program File\MyProgram\program.exe "parameters"
...
该错误仅发生在一种环境中。我知道应该对路径进行转义,但是subprocess.Popen
怎么可能处理带有空格而不转义的路径?
【问题讨论】:
相关/相同***.com/questions/804995/… cmd是字符串还是字符串列表? @beroe 类似,但不一样。就我而言,我只有一个工作方式不同的代码,有时它可以处理带有空格的路径,有时不能,我试图理解为什么。 @tdelaney 它是一个字符串 错误的回溯是什么? 【参考方案1】:带有空格的路径需要转义。最简单的方法是将命令设置为列表,添加 shell=True 并让 python 为您进行转义:
import subprocess
cmd = [r"C:\Program File\MyProgram\program.exe", "param1", "param2"]
process = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE,
stderr=subprocess.PIPE,stdin=subprocess.PIPE, close_fds=close_fds)
【讨论】:
感谢您的回复,但这不是我问题的答案。我的问题是 - 为什么同一段代码在几乎相同的 Windows 上的相同版本的 Python 上的工作方式不同,以及 subprocess.Popen 怎么可能处理带有空格的非转义路径。它应该被转义,但事实并非如此,这段代码有效,我想知道为什么。 使用shell=True
有问题(stderr 导致挂起)且不安全,因此不推荐。
@AlexanderTronchin-James - 越野车?如果 shell=True 导致挂起,这是我第一次听说它。 shell=True 确实存在命令注入的风险,因此不建议在任何地方使用它,但在许多情况下都可以合理使用它。例如构建系统。【参考方案2】:
对于偶然发现这篇文章并寻找解决方案的任何人,将可执行文件封装在引号中适用于 Windows,并将 ' ' 替换为 '\ ' 在 bash (Linux/MacOS) 中适用于 Popen shell 命令。
这对我有用:
from subprocess import Popen
cmd = '/path/to/some executable with spaces'
# Execute in Windows shell:
Popen(r'""'.format(cmd), shell=True)
# Execute in bash shell:
Popen(cmd.replace(' ', '\ '), shell=True)
【讨论】:
您需要致电cmd.replace(' ', '\\ ')
(带双反斜杠)【参考方案3】:
考虑一下:
command = "C:\Path argument\or\path"
如何区分带有参数argument\or\path
的可执行文件C:\Path
和位于C:\Path\ argument\or
的命令path
?但是,如果您将列表而不是字符串传递给 Popen
,则意图是明确的:
command = ["C:\Path argument\or\path"]
proc = Popen(command, ...)
【讨论】:
乔尔,感谢您的回复,但这不是问题的答案,请参阅我对@tdelaney 的评论 这是一个有效的答案。如果我的命令取自变量,则上述答案中的 r"" 解决方案不起作用。【参考方案4】:这是我发现适用于 windows 的:
以下任一语句都将使用指定的程序打开指定的文件:
subprocess.run('start EXCEL.exe "%s"' %cmd_path, shell=True)
os.system('start EXCEL.exe "%s"' %cmd_path)
不幸的是,subprocess.run 不适用于可迭代参数。以下对我来说不起作用:
subprocess.call(['start','EXCEL.EXE', f'"%s"'%save_path])
subprocess.run(['start','EXCEL.EXE', f"%s"%save_path])
os.system('start EXCEL.EXE ' + f"%s"%save_path)
【讨论】:
【参考方案5】:一个丑陋的解决方法,但是一个非常有效的解决方法 - 使用 python 使用您的命令创建批处理文件 - 执行批处理文件 - 删除批处理文件
def runThis(command):
tempBatch = open(r'c:\temp\TemporaryBatchFile.bat', 'w')
tempBatch.write(command)
tempBatch.close()
subprocess.call(r'c:\temp\TemporaryBatchFile.bat')
然后使用这样的东西:
runThis('start "C:\\Program Files\\Microsoft Office\\root\\Office16\\WINWORD.EXE" "' + Directory + '\\' + FileName + '"')
【讨论】:
以上是关于Python 的 subprocess.Popen 是不是接受路径中的空格?的主要内容,如果未能解决你的问题,请参考以下文章
查找 subprocess.Popen python 的执行时间
杀死使用 Python 的 subprocess.Popen() 创建的进程 [重复]