Аргумент функции, распаковывающий
, можно распаковать список или словарь как аргументы функции с помощью *
и **
.
, Например:
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 широко используются в качестве контейнеров.
Вы выполняете блокирующее чтение двух файлов; первый должен быть завершен до начала второго. Если приложение много пишет в stderr
и ничего не записывает в stdout
, то ваш процесс будет ждать данных на stdout
, которые не поступают, а программа, которую вы запускаете, сидит там, ожидая, когда будет прочитан материал, который она написала на stderr
(чего никогда не будет - поскольку вы ' повторное ожидание stdout
).
Есть несколько способов исправить это.
Самый простой - не перехватывать stderr
; оставить stderr = Нет
. Ошибки будут выводиться напрямую на stderr
. Вы не можете перехватить их и отобразить как часть собственного сообщения. Для инструментов командной строки это часто нормально. Для других приложений это может быть проблемой.
Другой простой подход - перенаправить stderr
на stdout
, чтобы у вас был только один входящий файл: set stderr = STDOUT
. Это означает, что вы не можете отличить обычный вывод от вывода ошибок. Это может быть приемлемым или неприемлемым, в зависимости от того, как приложение записывает выходные данные.
Полный и сложный способ справиться с этим - select
( http://docs.python.org/library /select.html ). Это позволяет вам читать неблокирующим образом: вы получаете данные всякий раз, когда данные появляются либо на stdout
, либо на stderr
. Я бы рекомендовал это только в том случае, если это действительно необходимо. Вероятно, это не работает в Windows.
Гленн Мейнард прав в своем комментарии о тупиках. Однако лучший способ решить эту проблему - создать два потока, один для stdout и один для stderr, которые читают эти соответствующие потоки до тех пор, пока не будут исчерпаны, и делают все, что вам нужно с выходными данными.
Предложение использовать временные файлы может или может не работать для вас в зависимости от размера вывода и т. д., а также от того, нужно ли вам обрабатывать вывод подпроцесса по мере его создания.
Как предложил Хейкки Тойвонен, вам следует изучить метод сообщения
. Однако это буферизует stdout / stderr подпроцесса в памяти, и вы получаете те, которые возвращаются вызовом communication
- это не идеально для некоторых сценариев. Но стоит обратить внимание на источник метода связи.
Другой пример - в поддерживаемом мной пакете, python-gnupg , где исполняемый файл gpg
порождается через подпроцесс
для выполнения тяжелой работы, а оболочка Python порождает потоки для чтения stdout и stderr gpg и использования их как данные производит gpg. Вы также можете почерпнуть некоторые идеи, просмотрев там источник. В общем случае данные, передаваемые gpg как на стандартный вывод, так и на стандартный поток, могут быть довольно большими.
Большая часть вывода является субъективной, поэтому дать рекомендацию немного сложно. Если объем вывода на самом деле велик, то вы, вероятно, все равно не захотите получать его все с помощью одного вызова 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
Вы можете попробовать связаться и посмотреть, решит ли это вашу проблему. Если нет, я бы перенаправил вывод во временный файл.