В чем разница между использованием universal_newlines=True (с bufsize=1) и использованием аргументов по умолчанию с Popen
Я пытаюсь прочитать вывод подпроцесса, вызванного из Python. Для этого я использую Popen (потому что я не думаю, что возможно использовать стандартный поток вывода при использовании subprocess.call).
На данный момент у меня есть два способа сделать это, которые в тестировании, кажется, дают одинаковые результаты. Код выглядит следующим образом:
with Popen(['Robocopy', source, destination, '/E', '/TEE', '/R:3', '/W:5', '/log+:log.txt'], stdout=PIPE) as Robocopy:
for line in Robocopy.stdout:
line = line.decode('ascii')
message_list = [item.strip(' \t\n').replace('\r', '') for item in line.split('\t') if item != '']
print(message_list[0], message_list[0])
Robocopy.wait()
returncode = Robocopy.returncode
а также
with Popen(['Robocopy', source, destination, '/E', '/TEE', '/R:3', '/W:5', '/log+:log.txt'], stdout=PIPE, universal_newlines=True, bufsize=1) as Robocopy:
for line in Robocopy.stdout:
message_list = [item.strip() for item in line.split('\t') if item != '']
print(message_list[0], message_list[2])
Robocopy.wait()
returncode = Robocopy.returncode
Первый метод не включает universal_newlines=True, поскольку в документации говорится, что он может использоваться только в случае универсального_newlines = True, т. Е. В текстовом режиме.
Вторая версия включает в себя universal_newlines, и поэтому я указываю размер буфера.
Может кто-нибудь объяснить мне разницу? Я не могу найти статью, но я читал о проблемах с переполнением буфера, вызывающих какие-то проблемы и, следовательно, важность использования for line in stdout
,
Кроме того, при просмотре выходных данных, если не указать universal_newlines, stdout становится bytes
объект - но я не уверен, какая разница, если я просто декодировать объект байтов с ascii
(с точки зрения новых строк и вкладок) сравнил режим universal_newlines.
Наконец, установка bufsize
в 1
делает вывод "буферизованным строкой", но я не уверен, что это значит. Я был бы признателен за объяснение того, как эти различные элементы связаны друг с другом. Спасибо
1 ответ
В чем разница между использованием universal_newlines=True (с bufsize=1) и использованием аргументов по умолчанию с Popen
Значения по умолчанию: universal_newlines=False
(то есть ввод / вывод принимается как байты, а не строки Юникода плюс универсальная обработка режима новой строки (отсюда и название параметра. Python 3.7 предоставляет text
псевдоним, который может быть более интуитивным здесь) отключен - вы получаете двоичные данные как есть (если только слой POSIX в Windows не испортил их) и bufsize=-1
(то есть потоки полностью буферизуются - используется размер буфера по умолчанию).
universal_newlines=True
использования locale.getpreferredencoding(False)
кодировка символов для декодирования байтов (которые могут отличаться от ascii
кодировка используется в вашем коде).
Если universal_newlines=False
затем for line in Robocopy.stdout:
перебирает b'\n'
разделенные линии. Если процесс использует не-ascii кодирование, например, UTF-16 для его вывода, то даже если os.linesep == '\n'
в вашей системе; Вы можете получить неправильный результат. Если вы хотите использовать текстовые строки, используйте текстовый режим: pass universal_newlines=True
или использовать io.TextIOWrapper(process.stdout)
в явном виде.
Вторая версия включает в себя universal_newlines, и поэтому я указываю размер буфера.
В общем, не нужно указывать bufsize
если вы используете universal_newlines
(Вы можете, но это не обязательно). И вам не нужно указывать bufsize
в твоем случае. bufsize=1
включает режим буферизации строки (входной буфер очищается автоматически на новых строках, если вы пишете в process.stdin
) в противном случае это эквивалентно умолчанию bufsize=-1
,