OSError:[Errno 2]在Django中使用python子进程时没有这样的文件或目录

San*_*tla 124 python django subprocess

我试图运行一个程序在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
Run Code Online (Sandbox Code Playgroud)

我的实际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)
Run Code Online (Sandbox Code Playgroud)

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

Ash*_*ary 273

使用shell=True,如果你传递一个字符串subprocess.call.

来自docs:

如果传递单个字符串,则shell必须是True或者字符串必须简单地命名要执行的程序而不指定任何参数.

subprocess.call(crop, shell=True)
Run Code Online (Sandbox Code Playgroud)

要么:

import shlex
subprocess.call(shlex.split(crop))
Run Code Online (Sandbox Code Playgroud)

  • @AnneTheAgile:`shell = True`不是必需的.此外,除非有必要,否则不应使用它(请参阅@ valid的评论).您应该将每个命令行参数作为单独的列表项传递,例如,使用`['command','arg 1','arg 2']`而不是``command'arg 1''arg 2'"`. (20认同)
  • 请注意,文档还声明"在外部输入构造命令字符串的情况下,强烈建议不要使用`shell = True`**",请参阅答案中的链接. (13认同)
  • Python 3提供了一个更好的错误消息,命名有问题的'文件',但它没有提示需要shell = True.谢谢! (6认同)
  • @ user3553031并不总是不建议这样做,文档明确指出,当输入“来自外部输入”时,这是不安全的。说您永远不要使用它是胡说八道。关于子流程的问题太多了,在每个答案中都没有提及这一点。已经有其他用户对此发表评论,并且我也共享了文档链接。欢迎您编辑我的答案。 (5认同)
  • @ user3553031我不建议在其他格式上使用它。我只是简单地指出了一个事实,如果您使用的是字符串,则必须使用`shell = True`。安全方面超出了此问题的范围。 (2认同)

Dan*_*kin 8

No such file or directory如果您尝试Popen使用双引号将文件参数放入,也可以引发。

例如:

call_args = ['mv', '"path/to/file with spaces.txt"', 'somewhere']
Run Code Online (Sandbox Code Playgroud)

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

call_args = ['mv', 'path/to/file with spaces.txt', 'somewhere']
Run Code Online (Sandbox Code Playgroud)


Dus*_*sic 7

无法投票,所以我会重新发布@jfs 评论,因为我认为它应该更明显。

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