subprocess.Popen
, když je vytvořena instance, spustí program. Nečeká na to – spustí jej na pozadí, jako byste zadali cmd &
ve skořápce. Takže ve výše uvedeném kódu jste v podstatě definovali podmínku sporu – pokud se vložky dokážou dokončit včas, bude to vypadat normálně, ale pokud ne, dostanete neočekávaný výstup. Nečekáte na svůj první run()
Pokud chcete PID dokončit, jednoduše vracíte jeho Popen
instance a pokračování.
Nejsem si jistý, jak toto chování odporuje dokumentaci, protože na Popenu je několik velmi jasných metod, které, jak se zdá, naznačují, že se na něj nečeká, jako:
Popen.wait()
Wait for child process to terminate. Set and return returncode attribute.
Souhlasím však s tím, že dokumentaci k tomuto modulu lze zlepšit.
Chcete-li počkat na dokončení programu, doporučuji použít subprocess
's pohodlný způsob, subprocess.call
nebo pomocí communicate
na Popen
objekt (pro případ, kdy potřebujete stdout). Už to děláte pro svůj druhý hovor.
### 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
Navíc ve většině případů nemusíte spouštět příkaz v shellu. Toto je jeden z těchto případů, ale budete muset svůj příkaz přepsat jako sekvenci. Pokud to uděláte tímto způsobem, také vám umožní vyhnout se tradičnímu vstřikování shellu a méně se starat o citování, jako například:
prog = ["mysql", "-u", "ve", "--execute", 'insert into foo values ("snargle", 2)']
subprocess.call(prog)
To bude dokonce fungovat a nebude vstřikováno tak, jak byste očekávali:
prog = ["printf", "%s", "<", "/etc/passwd"]
subprocess.call(prog)
Zkuste to interaktivně. Vyhnete se možnostem vkládání shellu, zvláště pokud přijímáte uživatelský vstup. Mám podezření, že pro komunikaci s podprocesem používáte méně úžasnou řetězcovou metodu, protože jste měli potíže s uvedením sekvencí do práce :^)