Блокирующие и неблокирующие вызовы подпроцесса

Я полностью запутался между 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.)

Другие вопросы по тегам