J'ai un problème avec la méthode subprocess.Popen de Python.Pourquoi le sous-processus.Popen n'attend pas jusqu'à ce que le processus fils se termine?
Voici un script de test qui illustre le problème. Il est exécuté sur une machine Linux.
#!/usr/bin/env python
import subprocess
import time
def run(cmd):
p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE)
return p
### 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'
run(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 = run(cmd)
count = (int(process.communicate()[0][:-1]))
# if subprocess.Popen() waited for the child to terminate than count should be
# greater than 0
if count > 0:
print "success: " + str(count)
else:
print "failure: " + str(count)
time.sleep(5)
# find out how many rows exists in the destination table after sleeping
process = run(cmd)
count = (int(process.communicate()[0][:-1]))
print "after sleeping the count is " + str(count)
Habituellement, la sortie de ce script est:
success: 100000
mais parfois il est
failure: 0
after sleeping the count is 100000
Notez que dans le cas d'échec, la sélection immédiatement après l'insertion montre 0 lignes, mais après dormir pendant 5 secondes une seconde sélection correctement affiche un nombre de lignes de 100000. Ma conclusion est que l'un des suivants est vrai:
- subprocess.Popen n'attend pas le fil de l'enfant de mettre fin - Cela semble contredire la documentation
- l'insert mysql n'est pas atomique - ma compréhension de MySQL semble indiquer insert est atomique
- select est pas voir le nombre de lignes correct tout de suite - selon un ami qui sait mysql mieux que je fais cela ne devrait pas se produire non plus
Qu'est-ce qui me manque? Je suis conscient que c'est une manière hacky d'interagir avec mysql de Python et MySQLdb n'aurait probablement pas ce problème, mais je suis curieux de savoir pourquoi cette méthode ne fonctionne pas.
Merci à tous pour les grandes réponses. En regardant à nouveau la documentation du sous-processus, je vois que le commentaire "Attendre la fin de la commande" apparaît dans les sections des méthodes de commodité et non dans la section de la méthode Popen. J'ai donné le signe de la tête à la réponse de Jed, car elle répondait mieux à ma question originale, mais je pense que je vais utiliser la solution de Paul pour mes futurs besoins de script. –
Gardez à l'esprit que os.system (à moins que vous ne fassiez autre chose avec) renvoie la VALEUR RENVOYÉE du processus (généralement 0 ou 1). Ne laissez pas cela vous mordre non plus. –