Используя подпроцесс. Popen для Процесса с Крупносерийным производством

Аргумент функции, распаковывающий

, можно распаковать список или словарь как аргументы функции с помощью * и **.

, Например:

def draw_point(x, y):
    # do some magic

point_foo = (3, 4)
point_bar = {'y': 3, 'x': 2}

draw_point(*point_foo)
draw_point(**point_bar)

Очень полезный ярлык начиная со списков, кортежи и dicts широко используются в качестве контейнеров.

31
задан SilentGhost 25 July 2009 в 19:40
поделиться

4 ответа

Вы выполняете блокирующее чтение двух файлов; первый должен быть завершен до начала второго. Если приложение много пишет в stderr и ничего не записывает в stdout , то ваш процесс будет ждать данных на stdout , которые не поступают, а программа, которую вы запускаете, сидит там, ожидая, когда будет прочитан материал, который она написала на stderr (чего никогда не будет - поскольку вы ' повторное ожидание stdout ).

Есть несколько способов исправить это.

Самый простой - не перехватывать stderr ; оставить stderr = Нет . Ошибки будут выводиться напрямую на stderr . Вы не можете перехватить их и отобразить как часть собственного сообщения. Для инструментов командной строки это часто нормально. Для других приложений это может быть проблемой.

Другой простой подход - перенаправить stderr на stdout , чтобы у вас был только один входящий файл: set stderr = STDOUT . Это означает, что вы не можете отличить обычный вывод от вывода ошибок. Это может быть приемлемым или неприемлемым, в зависимости от того, как приложение записывает выходные данные.

Полный и сложный способ справиться с этим - select ( http://docs.python.org/library /select.html ). Это позволяет вам читать неблокирующим образом: вы получаете данные всякий раз, когда данные появляются либо на stdout , либо на stderr . Я бы рекомендовал это только в том случае, если это действительно необходимо. Вероятно, это не работает в Windows.

18
ответ дан 27 November 2019 в 22:34
поделиться

Гленн Мейнард прав в своем комментарии о тупиках. Однако лучший способ решить эту проблему - создать два потока, один для stdout и один для stderr, которые читают эти соответствующие потоки до тех пор, пока не будут исчерпаны, и делают все, что вам нужно с выходными данными.

Предложение использовать временные файлы может или может не работать для вас в зависимости от размера вывода и т. д., а также от того, нужно ли вам обрабатывать вывод подпроцесса по мере его создания.

Как предложил Хейкки Тойвонен, вам следует изучить метод сообщения . Однако это буферизует stdout / stderr подпроцесса в памяти, и вы получаете те, которые возвращаются вызовом communication - это не идеально для некоторых сценариев. Но стоит обратить внимание на источник метода связи.

Другой пример - в поддерживаемом мной пакете, python-gnupg , где исполняемый файл gpg порождается через подпроцесс для выполнения тяжелой работы, а оболочка Python порождает потоки для чтения stdout и stderr gpg и использования их как данные производит gpg. Вы также можете почерпнуть некоторые идеи, просмотрев там источник. В общем случае данные, передаваемые gpg как на стандартный вывод, так и на стандартный поток, могут быть довольно большими.

6
ответ дан 27 November 2019 в 22:34
поделиться

Большая часть вывода является субъективной, поэтому дать рекомендацию немного сложно. Если объем вывода на самом деле велик, то вы, вероятно, все равно не захотите получать его все с помощью одного вызова read (). Вы можете попробовать записать вывод в файл, а затем извлекать данные постепенно, например:

f=file('data.out','w')
p = subprocess.Popen(cmd, shell=True, stdout=f, stderr=subprocess.PIPE)
errcode = p.wait()
f.close()
if errcode:
    errmess = p.stderr.read()
    log.error('cmd failed <%s>: %s' % (errcode,errmess))
for line in file('data.out'):
    #do something
6
ответ дан 27 November 2019 в 22:34
поделиться

Вы можете попробовать связаться и посмотреть, решит ли это вашу проблему. Если нет, я бы перенаправил вывод во временный файл.

2
ответ дан 27 November 2019 в 22:34
поделиться
Другие вопросы по тегам:

Похожие вопросы: