191

I am trying to run a program to make some system calls inside Python code using subprocess.call() which throws the following error:

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

My actual Python code is as follows:

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)

Can I get some relevant advice on how to solve this?

3

3 Answers 3

410

Use shell=True if you're passing a string to subprocess.call.

From docs:

If passing a single string, either shell must be True or else the string must simply name the program to be executed without specifying any arguments.

subprocess.call(crop, shell=True)

or:

import shlex
subprocess.call(shlex.split(crop))
13
  • 9
    Python 3 gives a better error message, naming the offending 'file', but it gives no hint that shell=True is required. Thank you! Commented Nov 8, 2014 at 0:04
  • 18
    Be aware, the docs also state "the use of shell=True is strongly discouraged in cases where the command string is constructed from external input", see link in the answer.
    – valid
    Commented Nov 12, 2014 at 4:01
  • 37
    @AnneTheAgile: shell=True is not required. Moreover you should not use it unless it is necessary (see @ valid's comment). You should pass each command-line argument as a separate list item instead e.g., use ['command', 'arg 1', 'arg 2'] instead of "command 'arg 1' 'arg 2'".
    – jfs
    Commented Mar 3, 2015 at 10:02
  • 3
    @user3553031 I am not recommending it over other formats. I have simply pointed out the fact if you're using a string then you will have to use shell=True. The security aspects are beyond the scope of this question. Commented Oct 31, 2017 at 5:09
  • 8
    @user3553031 It's not always discouraged, the documentation clearly says it is not safe when the input is coming from an external input. Saying you should not use it ever is nonsense. And there are so many questions about subprocess, it doesn't make any sense to mention this in every answer. There are already comments about it from other users and I have shared the link to documentation as well. You're welcome to edit my answer. Commented Oct 31, 2017 at 18:43
14

No such file or directory can be also raised if you are trying to put a file argument to Popen with double-quotes.

For example:

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

In this case, you need to remove double-quotes.

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

Can't upvote so I'll repost @jfs comment cause I think it should be more visible.

@AnneTheAgile: shell=True is not required. Moreover you should not use it unless it is necessary (see @ valid's comment). You should pass each command-line argument as a separate list item instead e.g., use ['command', 'arg 1', 'arg 2'] instead of "command 'arg 1' 'arg 2'". – jfs Mar 3 '15 at 10:02

Not the answer you're looking for? Browse other questions tagged or ask your own question.