Windows tidak dapat menemukan file di subprocess.call ()

103

Saya mendapatkan kesalahan berikut:

WindowsError: [Error 2] The system cannot find the file specified

Kode saya adalah:

subprocess.call(["<<executable file found in PATH>>"])

Windows 7, 64 bit. Python 3.x terbaru, stabil.

Ada ide?

Terima kasih,

Sri
sumber
dan apa file yang dapat dieksekusi ini?
SilentGhost
Bagian yang dapat dijalankan "android" dari Android SDK
Sri
2
Dan ini tersedia di PATH
Sri
dapatkah Anda menjalankannya dari baris perintah?
SilentGhost
Sedikit latar belakang tentang apa yang ingin saya capai. Ini untuk Opendevice - proyek open source untuk mengubah aplikasi HTML5 menjadi aplikasi khusus perangkat. Saya mencoba mengganti os.system () di bitbucket.org/srirangan/opendevice/src/tip/tools/net/srirangan/… ke subprocess.call ()
Sri

Jawaban:

178

Jika perintahnya adalah shell built-in, tambahkan 'shell = True' ke panggilan.

Misal untuk dirAnda akan mengetik:

import subprocess
subprocess.call('dir', shell=True)

Mengutip dari dokumentasi:

Satu-satunya waktu Anda perlu menentukan shell = True di Windows adalah ketika perintah yang ingin Anda jalankan sudah ada di dalam shell (misalnya dir atau copy). Anda tidak perlu shell = True untuk menjalankan file batch atau executable berbasis konsol.

Douglas Macdonald
sumber
14
Itu karena tidak ada eksekusi yang dipanggil dir.exesaat ada /bin/lsin * nix. dirdiimplementasikan oleh CMD.EXE seperti cdyang diterapkan oleh bash .
Apalala
1
Ini sangat tidak dianjurkan. docs.python.org/2/library/…
nu everest
11
@nueverest Hanya ketika string perintah dibuat dari input eksternal
Jirka
Alternatifnya (lebih aman untuk input eksternal) adalah mendapatkan PATHdari os.environdan mencarinya secara manual.
asmeurer
Lihat stackoverflow.com/a/32799942/3912576 untuk solusi yang jauh lebih tepat untuk masalah ini.
SimonBiggs
33

Di Windows, saya yakin subprocessmodul tidak melihat ke dalam PATHkecuali Anda lulusshell=True karena digunakan di CreateProcess()belakang layar. Namun, shell=Truebisa menjadi risiko keamanan jika Anda menyampaikan argumen yang mungkin datang dari luar program Anda. Agar subprocesstetap dapat menemukan file yang dapat dieksekusi dengan benar, Anda dapat menggunakan shutil.which. Misalkan yang dapat dieksekusi di Anda PATHdiberi nama frob:

subprocess.call([shutil.which('frob'), arg1, arg2])

(Ini berfungsi pada Python 3.3 dan yang lebih baru.)

ptomato
sumber
4
Ada opsi python 2?
Naramsim
1
Anda benar dan Anda menyarankan cara yang tepat untuk memperbaikinya. Jawaban ini harus diterima. Jawaban yang diterima saat ini tidak menjelaskan penyebabnya dan menyarankan perbaikan yang mungkin berbahaya dalam beberapa kasus.
David Ferenczy Rogožan
18

Di Windows, Anda harus memanggil melalui cmd.exe. Seperti yang disebutkan Apalala, perintah Windows diimplementasikan dalam cmd.exe bukan sebagai executable terpisah.

misalnya

subprocess.call(['cmd', '/c', 'dir'])

/ c memberi tahu cmd untuk menjalankan perintah ikuti

Ini lebih aman daripada menggunakan shell = True, yang memungkinkan injeksi shell.

Sam Inverso
sumber
Bagaimana saya menjaga layar tetap terbuka?
Moondra
2
@Moondra, Jika saya memahami Anda secara benar, coba /kalih-alih /c. Masuk cmd /?di baris perintah untuk detailnya.
Pengguna5910
@ User5910 Terima kasih. Akan mencobanya saat saya mendapat kesempatan.
Moondra
3

Jika Anda menggunakan PowerShell, maka di dalamnya akan tersedia subprocess.call(['powershell','-command','dir']). Powershell mendukung sebagian besar perintah POSIX

Darksnake
sumber
2

Setelah banyak garukan kepala, saya menemukan bahwa menjalankan file yang terletak di C: \ Windows \ System32 \ saat menjalankan versi python 32-bit pada mesin 64-bit adalah masalah potensial, karena Windows mencoba untuk mengungguli prosesnya, dan alihkan panggilan ke C: \ Windows \ System32 ke C: \ Windows \ SysWOW64.

Saya menemukan contoh cara memperbaikinya di sini: http://code.activestate.com/recipes/578035-disable-file-system-redirector/

RBN
sumber
1

Mengutip dari dokumentasi:

"Sebelum Python 3.5, ketiga fungsi ini terdiri dari API tingkat tinggi untuk subproses. Anda sekarang dapat menggunakan run () dalam banyak kasus, tetapi banyak kode yang ada memanggil fungsi ini."

SO: daripada menggunakan subprocess.call, gunakan subprocess.run untuk Python 3.5 dan yang lebih baru

Adrian Berca
sumber
Benar dan bermanfaat.
Erick G. Hagstrom
0

Saya menemui masalah yang sama ketika saya memanggil PHP. Alasannya adalah PHP tidak ada di PATH sehingga perintah PHP tidak ditemukan. Tetapi PowerShell menemukan itu memang ada di lokasi saat ini dan itu menyarankan untuk mengganti 'PHP' dengan '. \ PHP' jika saya mempercayai perintah ini. Kemudian itu berjalan dengan baik.

michael xie
sumber