Python - Windows - Popen(shlex.split(命令),shell = False导致OSError:[Errno 2]没有这样的文件或目录

时间:2014-05-22 13:55:54

标签: python windows popen

我正在运行此代码,该代码在OSX中运行良好,但在Windows上导致错误:

command = "C:\\progra~2\\itms\\iTMSTransporter -m verify -f /Volumes/Stuff/Temp/TMP_S_0_V_TV2.itmsp -u username -p password -o /Volumes/Stuff/Temp/TMP_S_0_V_TV2.itmsp/LOGFILE.txt -s provider -v eXtreme"
self.process1 = Popen(shlex.split(command), shell=False, stdin=PIPE)

我在Windows上收到的错误是:

WindowsError: [Error 2] The system cannot find the file specified

为什么它在Windows上给我这个错误?

2 个答案:

答案 0 :(得分:1)

由于删除\字符,您的shlex.split()会破坏您的路径。我们来看看:

import shlex
command = "C:\\progra~2\\itms\\iTMSTransporter -m verify -f  Volumes/Stuff/Temp/TMP_S_0_V_TV2.itmsp -u username -p password -o /Volumes/Stuff/Temp/TMP_S_0_V_TV2.itmsp/LOGFILE.txt -s provider -v eXtreme"
print shlex.split(command)

['C:progra~2itmsiTMSTransporter', '-m', 'verify', '-f', '/Volumes/Stuff/Temp/TMP_S_0_V_TV2.itmsp', '-u', 'username', '-p', 'password', '-o', '/Volumes/Stuff/Temp/TMP_S_0_V_TV2.itmsp/LOGFILE.txt', '-s', 'provider', '-v', 'eXtreme']

如您所见,可执行文件的路径不正确(C:progra~2itmsiTMSTransporter),因此Popen无法找到它。

将您的路径分隔符更改为/,这在Linux / Windows环境中都是安全的:

command = "C:/progra~2/itms/iTMSTransporter -m verify -f  Volumes/Stuff/Temp/TMP_S_0_V_TV2.itmsp -u username -p password -o /Volumes/Stuff/Temp/TMP_S_0_V_TV2.itmsp/LOGFILE.txt -s provider -v eXtreme"
print shlex.split(command)

['C:/progra~2/itms/iTMSTransporter', '-m', 'verify', '-f', 'Volumes/Stuff/Temp/TMP_S_0_V_TV2.itmsp', '-u', 'username', '-p', 'password', '-o', '/Volumes/Stuff/Temp/TMP_S_0_V_TV2.itmsp/LOGFILE.txt', '-s', 'provider', '-v', 'eXtreme']

Popen()将正确处理此路径。

答案 1 :(得分:0)

这可能会晚一点,但也许对其他有类似问题的人很有帮助。

开始之前:我通常在处理Windows路径时倾向于使用原始字符串,以方便复制粘贴,因为它接受单个反斜杠字符:

In [0]: "C:\\path\\to\\folder" == r"C:\path\to\folder"
Out[0]: True

Gabriel M's answer中所述,问题可能来自shlex吞下了反冲。在这个答案中,我想提供一种解决方案,而不是用斜杠代替反斜杠。

In [1]: import shlex

In [2]: command = r"C:\progra~2\itms\iTMSTransporter -m verify 
   ...: -f /Volumes/Stuff/Temp/TMP_S_0_V_TV2.itmsp -u username -p password
   ...: -o /Volumes/Stuff/Temp/TMP_S_0_V_TV2.itmsp/LOGFILE.txt -s provider -v eXtreme"

In [3]: shlex.split(command)[0]
Out[3]: 'C:progra~2itmsiTMSTransporter'

保持反斜杠的简单方法是将posix=False选项传递给shlex.split()

In [4]: shlex.split(command, posix=False)[0]
Out[4]: 'C:\\progra~2\\itms\\iTMSTransporter'

正如您在另一个答案的注释中所述,替换斜杠不能解决您的问题,这可能是您的实际问题在于您在-f-o中传递给脚本的路径。也许要编写脚本,您将那些路径传递给期望的反斜杠字符,或者想在路径中包含驱动器号。 –无论如何,如果您在过去6年中找到了他的解决方案以及该解决方案是什么,将会很有趣。


其他选项

您还可以使用pathlib提供Path方法的as_posix()(用于操作系统识别路径格式的python3标准库)来将路径转换为带正斜杠的字符串。这将导致shlex.split()输出中的正斜杠。如果您的路径来自变量,并且没有直接进行硬编码(在后一种情况下,您可能只需更改(反)斜杠),则这可能最有用:

In [5]: from pathlib import Path

In [6]: command = Path(r"C:\progra~2\itms\iTMSTransporter").as_posix() + " -m verify 
   ...: -f /Volumes/Stuff/Temp/TMP_S_0_V_TV2.itmsp -u username -p password
   ...: -o /Volumes/Stuff/Temp/TMP_S_0_V_TV2.itmsp/LOGFILE.txt -s provider -v eXtreme"

In [7]: shlex.split(command)[0]
Out[7]: 'C:/progra~2/itms/iTMSTransporter'

或者,以下内容– [4]的改进版本–在两种操作系统上均应适用。在这种情况下,posix是通过os.name确定的。这还取决于使用pathlib进行操作系统感知的路径格式化。

In [8]: import os

In [9]: command = str(Path(r"C:\progra~2\itms\iTMSTransporter")) + " -m verify 
   ...: -f /Volumes/Stuff/Temp/TMP_S_0_V_TV2.itmsp -u username -p password
   ...: -o /Volumes/Stuff/Temp/TMP_S_0_V_TV2.itmsp/LOGFILE.txt -s provider -v eXtreme"

In [10]: shlex.split(command, posix=(os.name == "posiX"))[0]
Out[10]: 'C:\\progra~2\\itms\\iTMSTransporter'