subprocess.Popen
, при создании экземпляра запускает программу. Однако он не ждет его - он запускает его в фоновом режиме, как если бы вы набрали cmd &
в оболочке. Итак, в приведенном выше коде вы, по сути, определили условие гонки - если вставки могут закончиться вовремя, оно будет выглядеть нормально, но если нет, вы получите неожиданный результат. Вы не ждете окончания действия вашего первого run()
dID, вы просто возвращаете его Popen
экземпляр и продолжаете.
Я не уверен, как такое поведение противоречит документации, потому что в Popen есть несколько очень четких методов, которые, кажется, указывают, что его не ожидали, например:
Popen.wait()
Wait for child process to terminate. Set and return returncode attribute.
Я согласен, однако, что документация для этого модуля может быть улучшена.
Чтобы дождаться завершения программы, я бы порекомендовал использовать удобный метод subprocess
, subprocess.call
или communicate
на объекте Popen
(для случая, когда вам нужен стандартный вывод). Вы уже делаете это для своего второго звонка.
### 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
Кроме того, в большинстве случаев вам не нужно запускать команду в оболочке. Это один из тех случаев, но вам придется переписать вашу команду как последовательность. Это также позволит вам избежать традиционных инъекций оболочки и меньше беспокоиться о цитировании, например:
prog = ["mysql", "-u", "ve", "--execute", 'insert into foo values ("snargle", 2)']
subprocess.call(prog)
Это будет даже работать, и не будет вводить, как вы ожидаете:
prog = ["printf", "%s", "<", "/etc/passwd"]
subprocess.call(prog)
Попробуйте в интерактивном режиме. Вы избегаете возможностей внедрения оболочки, особенно если вы принимаете пользовательский ввод. Я подозреваю, что вы используете менее удивительный строковый метод связи с подпроцессом, потому что у вас возникли проблемы с получением последовательностей: ^)