OSError: [Erro 2] Não existe esse arquivo ou diretório ao usar o subprocesso python no Django

137

Estou tentando executar um programa para fazer algumas chamadas de sistema dentro do código Python usando o subprocess.call()que lança o seguinte erro:

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

Meu código Python atual é o seguinte:

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)

Posso obter conselhos relevantes sobre como resolver isso?

Sandeep Mederametla
fonte
A pergunta que foi duplicada para esta pergunta tem uma resposta muito melhor. Essa pergunta deve ser reaberta e esta duplicada para ela.
user3553031

Respostas:

301

Use shell=Truese você estiver passando uma string para subprocess.call.

Dos documentos :

Se passar uma única string, shelldeve ser Trueou a string deve simplesmente nomear o programa a ser executado sem especificar nenhum argumento.

subprocess.call(crop, shell=True)

ou:

import shlex
subprocess.call(shlex.split(crop))
Ashwini Chaudhary
fonte
7
O Python 3 fornece uma mensagem de erro melhor, nomeando o 'arquivo' ofensivo, mas não dá a entender que shell = True é necessário. Obrigado!
AnneTheAgile
14
Esteja ciente de que os documentos também declaram "o uso de shell=Trueé fortemente desencorajado nos casos em que a cadeia de comandos é construída a partir de entrada externa", consulte o link na resposta.
válido
23
@AnneTheAgile: shell=Truenão é necessário. Além disso, você não deve usá-lo, a menos que seja necessário (consulte o comentário de @ valid). Você deve passar cada argumento da linha de comando como um item de lista separado, por exemplo, use em ['command', 'arg 1', 'arg 2']vez de "command 'arg 1' 'arg 2'".
JFS
3
@ user3553031 Não o recomendo em outros formatos. Simplesmente apontei o fato de que, se você estiver usando uma string, precisará usar shell=True. Os aspectos de segurança estão além do escopo desta pergunta.
Ashwini Chaudhary
6
@ user3553031 Nem sempre é desencorajado, a documentação diz claramente que não é seguro quando a entrada é proveniente de uma entrada externa . Dizer que você nunca deve usá-lo é um absurdo. E há tantas perguntas sobre o subprocesso que não faz sentido mencionar isso em todas as respostas. Já existem comentários de outros usuários e também compartilhei o link para a documentação. Você pode editar minha resposta.
Ashwini Chaudhary
5

Não é possível votar novamente, então vou repostar o comentário do @jfs porque acho que deve ser mais visível.

@AnneTheAgile: shell = True não é necessário. Além disso, você não deve usá-lo, a menos que seja necessário (consulte o comentário de @ valid). Você deve passar cada argumento da linha de comando como um item de lista separado. Por exemplo, use ['command', 'arg 1', 'arg 2'] em vez de "command 'arg 1' 'arg 2'". Jfs 03/03 '15 às 10:02

Dusan Maksic
fonte
2

No such file or directoryTambém pode ser gerado se você estiver tentando colocar um argumento de arquivo Popenentre aspas duplas.

Por exemplo:

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

Nesse caso, você precisa remover aspas duplas.

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