如何从Python执行程序?os.system由于路径中的空格而失败


273

我有一个需要执行外部程序的Python脚本,但由于某种原因失败。

如果我有以下脚本:

import os;
os.system("C:\\Temp\\a b c\\Notepad.exe");
raw_input();

然后它失败并显示以下错误:

无法将“ C:\ Temp \ a”识别为内部或外部命令,可操作程序或批处理文件。

如果我用引号将程序转义:

import os;
os.system('"C:\\Temp\\a b c\\Notepad.exe"');
raw_input();

然后就可以了。但是,如果添加一个参数,它将再次停止工作:

import os;
os.system('"C:\\Temp\\a b c\\Notepad.exe" "C:\\test.txt"');
raw_input();

什么是执行程序并等待其完成的正确方法?我不需要从中读取输出,因为它是一个可视程序,可以完成工作然后退出,但是我需要等待它完成。

还要注意,将程序移动到非间隔路径也不是一种选择。


这也不起作用:

import os;
os.system("'C:\\Temp\\a b c\\Notepad.exe'");
raw_input();

注意交换的单/双引号。

有或没有记事本的参数在这里,它失败并显示错误消息

文件名,目录名称或卷标签语法不正确。


使用这个:os.system(r'C:\temp\"a b c"\Notepad.exe') 或这个:os.system('C:\\temp\\"a b c"\\Notepad.exe')
chanzerre's

对于将来的访问者,如果要运行带有参数的应用程序(使用子过程)。您需要按空格分开参数,然后分别传递每个参数。例如,这来自bat文件:"C:\Program Files\GDAL\gdal_translate.exe" -ot byte -of GTIFF -scale -co PHOTOMETRIC=CMYK "cmyk-16.tif" "cmyk-8_out.tif"。在Python中,它变为:["C:\\Program Files\\GDAL\\gdal_translate.exe", "-ot", "byte", "-scale", "-co", "PHOTOMETRIC=CMYK", "input_cmyk-16.tif", "output_cmyk-8.tif"]
akinuri

Answers:


297

subprocess.call将避免必须处理各种shell的引用约定的问题。它接受列表,而不是字符串,因此参数更容易定界。即

import subprocess
subprocess.call(['C:\\Temp\\a b c\\Notepad.exe', 'C:\\test.txt'])

81
在Windows中使用原始字符串要简单得多:r“ C:\ Temp \ abc \ Notepad.exe”
PierreBdR

1
是的,os.exec *函数将替换当前进程,因此您的python进程将不会继续。在Unix上使用它们的方式更多,shell发出命令的一般方法是先在子进程中先fork(),然后执行exec()。
布赖恩

1
Windows方法是os.spawn系列,可以代替使用。子过程虽然更可移植,并且在控制过程(捕获输入/输出等)方面提供了更大的灵活性,所以是首选。
布赖恩

6
@PierreBdr:在某些情况下,原始字符串不起作用:您需要在末尾使用斜杠。例如r'c:\ foo \ bar \'。实际上,最好使用正斜杠来代替。Windows API接受了这些命令(尽管某些shell命令(例如,复制命令)并不总是如此)
Brian

1
对于python> = 3.5,subprocess.call应替换为subprocess.run docs.python.org/3/library/subprocess.html#older-high-level-api
gbonetti

67

这是另一种方式。

如果您使用的是Windows,则以下行为类似于双击资源管理器中的文件,或将文件名作为DOS“开始”命令的参数:用任何与扩展名相关联的应用程序(如果有)打开文件。 。

filepath = 'textfile.txt'
import os
os.startfile(filepath)

例:

import os
os.startfile('textfile.txt')

如果记事本与.txt文件相关联,这将使用记事本打开textfile.txt。


1
* nix系统是否具有等效功能?
罗梅诺2012年

@Romeno:您可以尝试:webbrowser.open("textfile.txt")它应该打开一个文本编辑器。另请参见“完全独立启动第二个程序,就像我只是双击它一样”。
jfs 2012年

在我的设置中,textfile.txt需要用引号引起来,例如:os.startfile('path\to\textfile.txt')
thdoan 2014年

34

最外面的引号由Python本身使用,Windows Shell看不到它。如上所述,Windows仅能理解双引号。Python将在Windows上将正斜杠转换为反斜杠,因此您可以使用

os.system('"C://Temp/a b c/Notepad.exe"')

'被Python使用,然后将“ C://Temp/abc/Notepad.exe”(作为Windows路径,不需要双反斜杠)传递给CMD.EXE。


1
os.system('curl URL > file')在我想查看cURL的进度表刷新真正大文件的情况下,这似乎是最好的。
Zach Young

如果一个反斜杠后的第一个字母都有特殊含义(即\t\n等),则该特定反斜杠必须加倍。成为Windows路径与此无关。
伊桑·弗曼

1
请注意,如果您os.system()在Windows上使用,则cmd窗口将打开并保持打开状态,直到您关闭其启动的进程为止。恕我直言,最好使用os.startfile()
thdoan 2014年

1
别忘了import os
Besi 2015年


19

至少在Windows 7和Python 3.1中,如果命令路径中有空格,则os.systemWindows希望在命令行中双引号。例如:

  TheCommand = '\"\"C:\\Temp\\a b c\\Notepad.exe\"\"'
  os.system(TheCommand)

一个让我感到困扰的现实示例是在VirtualBox中克隆驱动器。subprocess.call上面的解决方案由于某些访问权限问题而无法使用,但是当我双引号命令时,它os.system变得很高兴:

  TheCommand = '\"\"C:\\Program Files\\Sun\\VirtualBox\\VBoxManage.exe\" ' \
                 + ' clonehd \"' + OrigFile + '\" \"' + NewFile + '\"\"'
  os.system(TheCommand)

就是这样!我会去的subprocess,但有时os.system并且输入起来os.popen(...).read()会更快。顺便说一句,您不需要在单引号内转义双引号,即'""C:\\Temp\\a b c\\Notepad.exe""'会。
Tomasz Gandor

9
import win32api # if active state python is installed or install pywin32 package seperately

try: win32api.WinExec('NOTEPAD.exe') # Works seamlessly
except: pass

并且似乎不需要使用此方法引用,例如win32api.WinExec('pythonw.exe d:\ web2py \ web2py.py -K welcome')在后台启动web2py调度程序。
蒂姆·理查森

@rahul,它是否包含可执行文件的参数?因此,如果您希望记事本打开文件还是分开的?
2012年


3

我怀疑这与您在Windows中使用快捷方式时存在同样的问题...请尝试以下操作:

import os;
os.system("\"C:\\Temp\\a b c\\Notepad.exe\" C:\\test.txt");

抱歉,这也不起作用,已编辑问题以反映这一点。
拉瑟五世卡尔森

我觉得窗户只使用”,而不是“为引用这可能会工作,如果你改变了这个但是你还是会遇到问题,如果你有嵌入的报价等。
布莱恩

我以为两者兼而有之,但您可能是对的。我知道它在双引号中有效(在外壳中至少是)。
马修·沙利

+1这是最好的+ 1,Windows XP,2007年家庭版运行良好

0

假设我们要运行您的Django Web服务器(在Linux中),您的路径(path = '/home/<you>/<first-path-section> <second-path-section>')之间有空间,因此请执行以下操作:

import subprocess

args = ['{}/manage.py'.format('/home/<you>/<first-path-section> <second-path-section>'), 'runserver']
res = subprocess.Popen(args, stdout=subprocess.PIPE)
output, error_ = res.communicate()

if not error_:
    print(output)
else:
    print(error_)

[ 注意 ]:

  • 不要忘记访问权限: chmod 755 -R <'yor path'>
  • manage.py 可以辩解: chmod +x manage.py

0

对于Python 3.7,请使用subprocess.call。使用原始字符串来简化Windows路径:

import subprocess
subprocess.call([r'C:\Temp\Example\Notepad.exe', 'C:\test.txt'])

0

无需子流程,可以通过以下方式轻松实现

GitPath =“ C:\ Program Files \ Git \ git-bash.exe”#在mycase中,其GITBASH os.startfile(GitPath)中的应用程序文件路径

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.