在使用Python子进程、命令和参数时出现“OSError: [Errno 2] No such file or directory”的错误。

188

我正在尝试在 Python 代码中使用 subprocess.call() 进行一些系统调用,但是会抛出以下错误:

Traceback (most recent call last):
      File "<console>", line 1, in <module>
      File "/usr/lib/python2.7/subprocess.py", line 493, in call
      return Popen(*popenargs, **kwargs).wait()
      File "/usr/lib/python2.7/subprocess.py", line 679, in __init__
errread, errwrite)
      File "/usr/lib/python2.7/subprocess.py", line 1249, in _execute_child
      raise child_exception
      OSError: [Errno 2] No such file or directory

我的实际Python代码如下:

url = "/media/videos/3cf02324-43e5-4996-bbdf-6377df448ae4.mp4"
real_path = "/home/chanceapp/webapps/chanceapp/chanceapp"+url
fake_crop_path = "/home/chanceapp/webapps/chanceapp/chanceapp/fake1"+url
fake_rotate_path = "/home/chanceapp/webapps/chanceapp.chanceapp/fake2"+url
crop = "ffmpeg -i %s -vf "%(real_path)+"crop=400:400:0:0 "+ "-strict -2 %s"%(fake_crop_path)
rotate = "ffmpeg -i %s -vf "%(fake_crop_path)+"transpose=1 "+"%s"%(fake_rotate_path)
move_rotated = "mv"+" %s"%(fake_rotate_path)+" %s"%(real_path)
delete_cropped = "rm "+"%s"%(fake_crop_path)
#system calls:
subprocess.call(crop)

我可以得到一些解决这个问题的相关建议吗?


被重复的问题链接(https://dev59.com/kJDea4cB1Zd3GeqPjPzJ)有一个更好的答案。那个问题应该重新开放,而这个问题应该被重复到那个问题上。 - user3553031
这个回答解决了你的问题吗?Python subprocess.Popen() 错误(没有那个文件或目录) - mkrieger1
当我使用类似于'/path/to/files/*'这样的输入文件路径时,我遇到了这个错误。将其更改为'/path/to/files/'仍然复制了所有文件,并且没有抛出stat错误! - undefined
3个回答

402

如果您将字符串传递给 subprocess.call,请使用shell=True

来自文档

如果只传递一个字符串,则必须设置shell=True或者该字符串仅命名要执行的程序而不指定任何参数。

subprocess.call(crop, shell=True)
或者:
import shlex
subprocess.call(shlex.split(crop))

8
Python 3给出更好的错误信息,命名了有问题的“文件”,但没有提示需要使用shell=True参数。谢谢! - AnneTheAgile
18
请注意,文档还指出:“在从外部输入构建命令字符串的情况下,强烈不建议使用 shell=True”,请参见答案中的链接。 - valid
37
“shell=True”不是必需的,除非有必要(参见@valid的评论)。您应该将每个命令行参数作为单独的列表项传递,例如使用“['command','arg 1','arg 2']”而不是“'command' 'arg 1' 'arg 2'”。 - jfs
3
我不建议优先选择它而不是其他格式。我只是指出一个事实,如果你正在使用一个字符串,那么你将不得不使用 shell=True。安全方面的问题超出了这个问题的范围。 - Ashwini Chaudhary
8
@user3553031,并不总是反对使用subprocess,文档明确指出,当输入来自于外部输入时使用它是不安全的。说永远不应该使用它是无意义的。而且有很多关于subprocess的问题,每个答案都提到这点没有任何意义。其他用户已经在评论中提到了这一点,我也分享了文档链接。欢迎您编辑我的回答。 - Ashwini Chaudhary
显示剩余8条评论

13
No such file or directory可能会被引发,如果您尝试使用双引号将文件参数放入Popen中。
例如:
call_args = ['mv', '"path/to/file with spaces.txt"', 'somewhere']

在这种情况下,您需要删除双引号。

call_args = ['mv', 'path/to/file with spaces.txt', 'somewhere']

9

由于无法点赞,因此我会转发@jfs的评论,因为我认为它应该更加显眼。

@AnneTheAgile: shell=True不是必须的。此外,除非必要(请参见@valid的评论),否则不应使用它。您应该将每个命令行参数作为单独的列表项传递,例如,使用['command','arg 1','arg 2']而不是“command'arg 1''arg 2'”- jfs Mar 3 '15 at 10:02


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接