OSError: [Errno 2] Aucun fichier ou répertoire de ce type lors de l'utilisation du sous-processus python dans Django

137

J'essaie d'exécuter un programme pour effectuer des appels système à l'intérieur du code Python à l'aide de subprocess.call()ce qui génère l'erreur suivante:

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

Mon code Python actuel est le suivant:

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)

Puis-je obtenir des conseils pertinents sur la façon de résoudre ce problème?

Sandeep Mederametla
la source
La question qui a été dupliquée à cette question a une bien meilleure réponse. Cette question devrait être rouverte et celle-ci dupliquée à la place.
user3553031

Réponses:

301

À utiliser shell=Truesi vous passez une chaîne à subprocess.call.

À partir de la documentation :

Si vous passez une seule chaîne, soit shelldoit être, Truesoit la chaîne doit simplement nommer le programme à exécuter sans spécifier d'arguments.

subprocess.call(crop, shell=True)

ou:

import shlex
subprocess.call(shlex.split(crop))
Ashwini Chaudhary
la source
7
Python 3 donne un meilleur message d'erreur, nommant le 'fichier' incriminé, mais il ne donne aucun indice que shell = True est requis. Je vous remercie!
AnneTheAgile
14
Attention, la documentation indique également que «l'utilisation de shell=Trueest fortement déconseillée dans les cas où la chaîne de commande est construite à partir d'une entrée externe», voir le lien dans la réponse.
valable
23
@AnneTheAgile: shell=Truen'est pas obligatoire. De plus, vous ne devriez pas l'utiliser sauf si c'est nécessaire (voir le commentaire de @ valid). Vous devez plutôt passer chaque argument de ligne de commande comme un élément de liste distinct, par exemple, utilisez à la ['command', 'arg 1', 'arg 2']place de "command 'arg 1' 'arg 2'".
jfs
3
@ user3553031 Je ne le recommande pas par rapport à d'autres formats. J'ai simplement souligné le fait que si vous utilisez une chaîne, vous devrez l'utiliser shell=True. Les aspects de sécurité sortent du cadre de cette question.
Ashwini Chaudhary
6
@ user3553031 Ce n'est pas toujours déconseillé, la documentation indique clairement que ce n'est pas sûr lorsque l'entrée provient d'une entrée externe . Dire que vous ne devriez jamais l'utiliser est un non-sens. Et il y a tellement de questions sur le sous-processus, cela n'a aucun sens de le mentionner dans chaque réponse. Il y a déjà des commentaires à ce sujet d'autres utilisateurs et j'ai également partagé le lien vers la documentation. Vous êtes invité à modifier ma réponse.
Ashwini Chaudhary
5

Je ne peux pas voter, alors je republierai le commentaire @jfs car je pense qu'il devrait être plus visible.

@AnneTheAgile: shell = True n'est pas obligatoire. De plus, vous ne devriez pas l'utiliser sauf si c'est nécessaire (voir le commentaire de @ valid). Vous devriez plutôt passer chaque argument de ligne de commande comme un élément de liste séparé, par exemple, utilisez ['command', 'arg 1', 'arg 2'] au lieu de "command 'arg 1' 'arg 2'". - jfs 3 mars 15 à 10:02

Dusan Maksic
la source
2

No such file or directorypeut également être déclenché si vous essayez de placer un argument de fichier Popenavec des guillemets.

Par exemple:

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

Dans ce cas, vous devez supprimer les guillemets.

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