subprocess.Popen
, ketika dipakai, menjalankan program. Namun, ia tidak menunggu -- ia mengaktifkannya di latar belakang seolah-olah Anda mengetik cmd &
dalam sebuah cangkang. Jadi, dalam kode di atas, pada dasarnya Anda telah mendefinisikan kondisi balapan -- jika penyisipan dapat selesai tepat waktu, itu akan tampak normal, tetapi jika tidak, Anda mendapatkan hasil yang tidak diharapkan. Anda tidak menunggu run()
pertama Anda 'd PID selesai, Anda cukup mengembalikan Popen
-nya contoh dan melanjutkan.
Saya tidak yakin bagaimana perilaku ini bertentangan dengan dokumentasi, karena ada beberapa metode yang sangat jelas di Popen yang tampaknya menunjukkan bahwa itu tidak menunggu, seperti:
Popen.wait()
Wait for child process to terminate. Set and return returncode attribute.
Namun, saya setuju bahwa dokumentasi untuk modul ini dapat ditingkatkan.
Untuk menunggu program selesai, saya sarankan menggunakan subprocess
metode kenyamanan, subprocess.call
, atau menggunakan communicate
pada Popen
objek (untuk kasus ketika Anda membutuhkan stdout). Anda sudah melakukan ini untuk panggilan kedua Anda.
### START MAIN
# copy some rows from a source table to a destination table
# note that the destination table is empty when this script is run
cmd = 'mysql -u ve --skip-column-names --batch --execute="insert into destination (select * from source limit 100000)" test'
subprocess.call(cmd)
# check to see how many rows exist in the destination table
cmd = 'mysql -u ve --skip-column-names --batch --execute="select count(*) from destination" test'
process = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE)
try: count = (int(process.communicate()[0][:-1]))
except: count = 0
Selain itu, dalam banyak kasus, Anda tidak perlu menjalankan perintah di shell. Ini adalah salah satu dari kasus tersebut, tetapi Anda harus menulis ulang perintah Anda seperti sebuah urutan. Melakukannya dengan cara itu juga memungkinkan Anda menghindari injeksi shell tradisional dan tidak terlalu khawatir tentang mengutip, seperti:
prog = ["mysql", "-u", "ve", "--execute", 'insert into foo values ("snargle", 2)']
subprocess.call(prog)
Ini bahkan akan berfungsi, dan tidak akan menyuntikkan seperti yang Anda harapkan:
prog = ["printf", "%s", "<", "/etc/passwd"]
subprocess.call(prog)
Cobalah secara interaktif. Anda menghindari kemungkinan injeksi shell, terutama jika Anda menerima input pengguna. Saya menduga Anda menggunakan metode string yang kurang bagus untuk berkomunikasi dengan subproses karena Anda mengalami kesulitan untuk membuat urutannya berfungsi :^)