Блокирующие и неблокирующие вызовы подпроцесса
Я полностью запутался между subprocess.call()
, subprocess.Popen()
, subprocess.check_call()
,
Что блокирует, а что нет?
Что я хочу сказать, если я использую subprocess.Popen()
ожидает ли родительский процесс дочерний процесс return
/exit
прежде чем продолжать его выполнение.
Как shell=True
повлиять на эти звонки?
1 ответ
Popen
неблокирует call
а также check_call
блокируют. Вы можете сделать Popen
экземпляр блока, вызвав его wait
или же communicate
метод.
Если вы посмотрите в исходном коде, вы увидите call
звонки Popen(...).wait()
Вот почему это блокирует. check_call
звонки call
Вот почему он также блокирует.
Строго говоря, shell=True
является ортогональным к вопросу блокировки. Тем не мение, shell=True
заставляет Python выполнить оболочку и затем запустить команду в оболочке. Если вы используете блокирующий вызов, он вернется после завершения оболочки. Так как оболочка может порождать подпроцесс для выполнения команды, оболочка может завершиться раньше, чем порожденный подпроцесс. Например,
import subprocess
import time
proc = subprocess.Popen('ls -lRa /', shell=True)
time.sleep(3)
proc.terminate()
proc.wait()
Здесь создаются два процесса: Popen порождает один подпроцесс, выполняющий оболочку. Оболочка, в свою очередь, порождает запущенный подпроцесс ls
, proc.terminate()
убивает оболочку, но работает подпроцесс ls
остается. (Это проявляется в обильном выводе даже после завершения сценария python. Будьте готовы убить ls
с pkill ls
.)