OSError: [Errno 2] No existe tal archivo o directorio mientras se usa el subproceso de python en Django

137

Estoy tratando de ejecutar un programa para hacer algunas llamadas al sistema dentro del código de Python subprocess.call()que arroja el siguiente 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

Mi código actual de Python es el siguiente:

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)

¿Puedo obtener algunos consejos relevantes sobre cómo resolver esto?

Sandeep Mederametla
fuente
La pregunta que fue duplicada a esta pregunta tiene una respuesta mucho mejor. Esa pregunta debe volver a abrirse y esta debe duplicarse en su lugar.
user3553031

Respuestas:

301

Úselo shell=Truesi está pasando una cadena a subprocess.call.

De documentos :

Si pasa una sola cadena, shelldebe ser Trueo la cadena simplemente debe nombrar el programa a ejecutar sin especificar ningún argumento.

subprocess.call(crop, shell=True)

o:

import shlex
subprocess.call(shlex.split(crop))
Ashwini Chaudhary
fuente
77
Python 3 da un mejor mensaje de error, nombrando el 'archivo' ofensivo, pero no da ninguna pista de que se requiere shell = True. ¡Gracias!
AnneTheAgile
14
Tenga en cuenta que los documentos también indican que " shell=Truese desaconseja encarecidamente el uso en los casos en que la cadena de comandos se construya a partir de una entrada externa", consulte el enlace en la respuesta.
válido el
23
@AnneTheAgile: shell=Trueno es obligatorio. Además, no debe usarlo a menos que sea necesario (vea el comentario de @ valid). En su lugar, debe pasar cada argumento de la línea de comandos como un elemento de lista separado, por ejemplo, use en ['command', 'arg 1', 'arg 2']lugar de "command 'arg 1' 'arg 2'".
jfs
3
@ user3553031 No lo recomiendo sobre otros formatos. Simplemente he señalado el hecho de que si está utilizando una cadena, tendrá que usarla shell=True. Los aspectos de seguridad están más allá del alcance de esta pregunta.
Ashwini Chaudhary
66
@ user3553031 No siempre se desaconseja, la documentación dice claramente que no es seguro cuando la entrada proviene de una entrada externa . Decir que no debes usarlo nunca es una tontería. Y hay tantas preguntas sobre el subproceso que no tiene sentido mencionar esto en cada respuesta. Ya hay comentarios al respecto de otros usuarios y también he compartido el enlace a la documentación. Puedes editar mi respuesta.
Ashwini Chaudhary
5

No puedo votar, así que volveré a publicar el comentario de @jfs porque creo que debería ser más visible.

@AnneTheAgile: shell = True no es necesario. Además, no debe usarlo a menos que sea necesario (vea el comentario de @ valid). En su lugar, debe pasar cada argumento de la línea de comandos como un elemento de lista separado, por ejemplo, usar ['comando', 'arg 1', 'arg 2'] en lugar de "comando 'arg 1' 'arg 2'". - jfs 3 de marzo de 15 a 10:02

Dusan Maksic
fuente
2

No such file or directorytambién puede aparecer si está tratando de poner un argumento de archivo Popencon comillas dobles.

Por ejemplo:

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

En este caso, debe eliminar las comillas dobles.

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