Saya memanggil berbagai proses dengan subprocess
modul. Namun, saya punya pertanyaan.
Dalam kode berikut:
callProcess = subprocess.Popen(['ls', '-l'], shell=True)
dan
callProcess = subprocess.Popen(['ls', '-l']) # without shell
Keduanya bekerja. Setelah membaca dokumen, saya jadi tahu itu shell=True
berarti mengeksekusi kode melalui shell. Jadi itu berarti saat tidak ada, prosesnya langsung dimulai.
Jadi apa yang harus saya sukai untuk kasus saya - saya perlu menjalankan proses dan mendapatkan hasilnya. Apa untungnya saya memanggilnya dari dalam shell atau di luarnya.
python
subprocess
pengguna225312
sumber
sumber
-l
dilewatkan ke/bin/sh
(shell) alih-alihls
program di Unix jikashell=True
. Argumen string harus digunakan denganshell=True
dalam banyak kasus, bukan daftar.shell=True
keFalse
dan sebaliknya adalah kesalahan. Dari dokumen : "Pada POSIX dengan shell = True, (...) Jika args adalah suatu urutan, item pertama menentukan string perintah, dan setiap item tambahan akan diperlakukan sebagai argumen tambahan untuk shell itu sendiri.". Di Windows ada konversi otomatis , yang mungkin tidak diinginkan.Jawaban:
Manfaat tidak menelepon melalui shell adalah Anda tidak menggunakan 'program misteri'. Pada POSIX, variabel lingkungan
SHELL
mengontrol biner yang dipanggil sebagai "shell." Di Windows, tidak ada turunan shell bourne, hanya cmd.exe.Jadi memohon shell memanggil program yang dipilih pengguna dan bergantung pada platform. Secara umum, hindari doa melalui shell.
Meminta melalui shell tidak memungkinkan Anda untuk memperluas variabel lingkungan dan file gumpalan sesuai dengan mekanisme shell yang biasa. Pada sistem POSIX, shell memperluas gumpalan file ke daftar file. Pada Windows, segumpal berkas (misalnya, "*. *") Tidak diperluas oleh shell, sih (tapi variabel lingkungan pada baris perintah yang diperluas oleh cmd.exe).
Jika Anda pikir Anda ingin ekspansi variabel lingkungan dan gumpalan file, telusuri
ILS
serangan tahun 1992-ish pada layanan jaringan yang melakukan pemanggilan subprogram melalui shell. Contohnya termasuk berbagaisendmail
backdoors yang terlibatILS
.Singkatnya, gunakan
shell=False
.sumber
$SHELL
itu tidak benar. Mengutip subprocess.html: "Pada Unix withshell=True
, shell default ke/bin/sh
." (tidak$SHELL
)open
jika Anda ingin cara aman untuk menjalankan program dan menangkap hasilnya.sumber: Modul Subproses
sumber
Contoh di mana ada yang salah dengan Shell = True ditampilkan di sini
Periksa dokumen di sini: subprocess.call ()
sumber
Menjalankan program melalui shell berarti bahwa semua input pengguna yang diteruskan ke program ditafsirkan sesuai dengan sintaks dan aturan semantik dari shell yang dipanggil. Paling-paling, ini hanya menyebabkan ketidaknyamanan bagi pengguna, karena pengguna harus mematuhi aturan-aturan ini. Misalnya, jalur yang berisi karakter shell khusus seperti tanda kutip atau kosong harus diloloskan. Paling buruk, itu menyebabkan kebocoran keamanan, karena pengguna dapat menjalankan program sewenang-wenang.
shell=True
kadang-kadang nyaman untuk menggunakan fitur shell tertentu seperti pemisahan kata atau ekspansi parameter. Namun, jika fitur seperti itu diperlukan, manfaatkan modul lain yang diberikan kepada Anda (misalnyaos.path.expandvars()
untuk perluasan parameter ataushlex
untuk pemisahan kata). Ini berarti lebih banyak pekerjaan, tetapi menghindari masalah lain.Singkatnya: Hindari
shell=True
dengan segala cara.sumber
Jawaban lain di sini cukup menjelaskan peringatan keamanan yang juga disebutkan dalam
subprocess
dokumentasi. Tetapi selain itu, overhead memulai shell untuk memulai program yang ingin Anda jalankan seringkali tidak perlu dan tentu saja konyol untuk situasi di mana Anda tidak benar-benar menggunakan fungsionalitas shell. Selain itu, kompleksitas tersembunyi tambahan akan membuat Anda takut, terutama jika Anda tidak terlalu mengenal shell atau layanan yang disediakannya.Di mana interaksi dengan shell adalah non-trivial, Anda sekarang memerlukan pembaca dan pengelola skrip Python (yang mungkin atau mungkin bukan diri Anda di masa depan) untuk memahami skrip Python dan shell. Ingat moto Python "eksplisit lebih baik daripada implisit"; bahkan ketika kode Python akan menjadi sedikit lebih kompleks daripada skrip shell yang setara (dan seringkali sangat singkat), Anda mungkin lebih baik menghapus shell dan mengganti fungsi dengan konstruksi Python asli. Meminimalkan pekerjaan yang dilakukan dalam proses eksternal dan menjaga kontrol dalam kode Anda sendiri sejauh mungkin seringkali merupakan ide yang baik hanya karena meningkatkan visibilitas dan mengurangi risiko efek samping yang diinginkan atau tidak diinginkan.
Ekspansi wildcard, interpolasi variabel, dan pengalihan semuanya mudah untuk diganti dengan konstruksi Python asli. Sebuah pipeline shell yang kompleks di mana sebagian atau semua tidak dapat ditulis ulang secara wajar dengan Python akan menjadi satu situasi di mana mungkin Anda bisa mempertimbangkan untuk menggunakan shell. Anda harus tetap memastikan bahwa Anda memahami implikasi kinerja dan keamanan.
Dalam kasus sepele, untuk menghindari
shell=True
, cukup gantidengan
Perhatikan bagaimana argumen pertama adalah daftar string untuk diteruskan
execvp()
, dan bagaimana mengutip string dan karakter karakter shell backslash-escape umumnya tidak diperlukan (atau berguna, atau benar). Mungkin lihat juga Kapan membungkus tanda kutip di sekitar variabel shell?Sebagai tambahan, Anda sangat sering ingin menghindari
Popen
jika salah satu pembungkus sederhana dalamsubprocess
paket melakukan apa yang Anda inginkan. Jika Anda memiliki Python yang cukup baru, Anda mungkin harus menggunakansubprocess.run
.check=True
itu akan gagal jika perintah yang Anda jalankan gagal.stdout=subprocess.PIPE
itu akan menangkap output perintah.universal_newlines=True
itu akan mendekode output menjadi string Unicode yang tepat (itu hanyabytes
dalam sistem pengkodean sebaliknya, pada Python 3).Jika tidak, untuk banyak tugas, Anda ingin
check_output
mendapatkan output dari perintah, sambil memeriksa apakah berhasil, ataucheck_call
jika tidak ada output untuk dikumpulkan.Saya akan menutup dengan kutipan dari David Korn: "Lebih mudah untuk menulis shell portabel daripada skrip shell portabel." Bahkan
subprocess.run('echo "$HOME"', shell=True)
tidak portabel untuk Windows.sumber
shell=True
, banyak di antaranya dengan jawaban yang sangat baik. Anda kebetulan memilih yang itulah mengapa .subprocess