В чем разница между использованием 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,

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