subprocess.Popen
, när instansierat, kör programmet. Den väntar dock inte på den – den avfyras i bakgrunden som om du hade skrivit cmd &
i ett skal. Så, i koden ovan, har du i princip definierat ett tävlingstillstånd - om skären kan sluta i tid kommer det att se normalt ut, men om inte får du den oväntade utsignalen. Du väntar inte på din första run()
Om du vill avsluta PID, returnerar du helt enkelt dess Popen
instans och fortsätter.
Jag är inte säker på hur detta beteende motsäger dokumentationen, eftersom det finns några mycket tydliga metoder på Popen som verkar indikera att det inte är väntat, som:
Popen.wait()
Wait for child process to terminate. Set and return returncode attribute.
Jag håller dock med om att dokumentationen för denna modul kan förbättras.
För att vänta på att programmet ska avslutas rekommenderar jag att du använder subprocess
s bekvämlighetsmetod, subprocess.call
, eller med communicate
på en Popen
objekt (för fallet när du behöver stdout). Du gör redan detta för ditt andra samtal.
### 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
Dessutom behöver du i de flesta fall inte köra kommandot i ett skal. Detta är ett av dessa fall, men du måste skriva om ditt kommando som en sekvens. Om du gör det på det sättet kan du också undvika traditionell skalinjektion och oroa dig mindre för att citera, som så:
prog = ["mysql", "-u", "ve", "--execute", 'insert into foo values ("snargle", 2)']
subprocess.call(prog)
Detta kommer till och med att fungera och kommer inte att injicera som du kan förvänta dig:
prog = ["printf", "%s", "<", "/etc/passwd"]
subprocess.call(prog)
Prova det interaktivt. Du undviker möjligheterna med skalinjektion, särskilt om du accepterar användarinput. Jag misstänker att du använder den mindre fantastiska strängmetoden för att kommunicera med subprocess eftersom du stötte på problem med att få sekvenserna att fungera :^)