OSError: [Errno 2] Tidak ada file atau direktori seperti itu saat menggunakan subproses python di Django

137

Saya mencoba menjalankan program untuk membuat beberapa panggilan sistem di dalam kode Python yang menggunakan subprocess.call()kesalahan berikut:

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

Kode Python saya yang sebenarnya adalah sebagai berikut:

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)

Bisakah saya mendapatkan saran yang relevan tentang cara mengatasi ini?

Sandeep Mederametla
sumber
Pertanyaan yang diduplikasi untuk pertanyaan ini memiliki jawaban yang jauh lebih baik. Pertanyaan itu harus dibuka kembali dan yang ini digandakan untuk itu.
user3553031

Jawaban:

301

Gunakan shell=Truejika Anda meneruskan string ke subprocess.call.

Dari dokumen :

Jika melewati string tunggal, shellharus berupa Truestring atau yang lain harus dengan mudah memberi nama program yang akan dieksekusi tanpa menentukan argumen apa pun.

subprocess.call(crop, shell=True)

atau:

import shlex
subprocess.call(shlex.split(crop))
Ashwini Chaudhary
sumber
7
Python 3 memberikan pesan kesalahan yang lebih baik, menamai 'file' yang menyinggung, tetapi tidak memberikan petunjuk bahwa shell = True diperlukan. Terima kasih!
AnneTheAgile
14
Sadarilah, dokumentasi juga negara "penggunaan shell=Trueyang sangat tidak dianjurkan dalam kasus di mana perintah string dibangun dari input eksternal", lihat link dalam jawaban.
berlaku
23
@AnneTheAgile: shell=Truetidak diperlukan. Selain itu Anda tidak boleh menggunakannya kecuali diperlukan (lihat komentar @ valid). Anda harus melewati setiap argumen baris perintah sebagai item daftar yang terpisah, misalnya, gunakan ['command', 'arg 1', 'arg 2']sebagai ganti "command 'arg 1' 'arg 2'".
jfs
3
@ user3553031 Saya tidak merekomendasikan ini di atas format lain. Saya hanya menunjukkan fakta jika Anda menggunakan string maka Anda harus menggunakan shell=True. Aspek keamanan berada di luar cakupan pertanyaan ini.
Ashwini Chaudhary
6
@ user3553031 Tidak selalu berkecil hati, dokumentasi dengan jelas mengatakan itu tidak aman ketika input berasal dari input eksternal . Mengatakan Anda tidak boleh menggunakannya adalah omong kosong. Dan ada begitu banyak pertanyaan tentang subproses, tidak masuk akal untuk menyebutkan ini dalam setiap jawaban. Sudah ada komentar tentang hal itu dari pengguna lain dan saya telah membagikan tautan ke dokumentasi juga. Anda boleh mengedit jawaban saya.
Ashwini Chaudhary
5

Tidak dapat mengunggah, jadi saya akan memposting ulang komentar @ jfs karena saya pikir itu harus lebih terlihat.

@AnneTheAgile: shell = True tidak diperlukan. Selain itu Anda tidak boleh menggunakannya kecuali diperlukan (lihat komentar @ valid). Anda harus melewati setiap argumen baris perintah sebagai item daftar terpisah, misalnya, gunakan ['command', 'arg 1', 'arg 2'] alih-alih "command 'arg 1' 'arg 2'". - jfs 3 Maret 15 jam 10:02

Dusan Maksic
sumber
2

No such file or directorydapat juga dimunculkan jika Anda mencoba untuk mengajukan argumen file Popendengan tanda kutip ganda.

Sebagai contoh:

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

Dalam hal ini, Anda perlu menghapus tanda kutip ganda.

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