subprocess.Popen
, po utworzeniu wystąpienia uruchamia program. Jednak nie czeka na to - uruchamia go w tle, tak jakbyś wpisał cmd &
w powłoce. Tak więc w powyższym kodzie zasadniczo zdefiniowałeś sytuację wyścigu -- jeśli wstawki mogą zakończyć się na czas, będą wyglądać normalnie, ale jeśli nie, otrzymasz nieoczekiwane wyjście. Nie czekasz na swój pierwszy run()
Jeśli PID się zakończy, po prostu zwracasz jego Popen
wystąpienie i kontynuacja.
Nie jestem pewien, w jaki sposób to zachowanie jest sprzeczne z dokumentacją, ponieważ istnieje kilka bardzo jasnych metod na Popen, które wydają się wskazywać, że nie jest to oczekiwane, takie jak:
Popen.wait()
Wait for child process to terminate. Set and return returncode attribute.
Zgadzam się jednak, że dokumentacja tego modułu może zostać ulepszona.
Aby poczekać na zakończenie programu, polecam użyć subprocess
wygodna metoda, subprocess.call
lub używając communicate
na Popen
obiekt (w przypadku, gdy potrzebujesz stdout). Robisz to już podczas drugiego połączenia.
### 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
Dodatkowo w większości przypadków nie trzeba uruchamiać polecenia w powłoce. To jeden z tych przypadków, ale będziesz musiał przepisać swoje polecenie jak sekwencję. Robienie tego w ten sposób pozwala również uniknąć tradycyjnego wstrzykiwania powłoki i mniej martwić się o cytowanie, na przykład:
prog = ["mysql", "-u", "ve", "--execute", 'insert into foo values ("snargle", 2)']
subprocess.call(prog)
To nawet zadziała i nie będzie wstrzykiwać zgodnie z oczekiwaniami:
prog = ["printf", "%s", "<", "/etc/passwd"]
subprocess.call(prog)
Wypróbuj to interaktywnie. Unikasz możliwości wstrzykiwania powłoki, szczególnie jeśli akceptujesz dane wejściowe użytkownika. Podejrzewam, że używasz mniej niesamowitej metody łańcuchowej komunikowania się z podprocesem, ponieważ masz problemy z uruchomieniem sekwencji :^)