Поймать универсальные переводы строки, но сохранить оригинал - PullRequest
0 голосов
/ 23 июня 2019

Так что это моя проблема,

Я пытаюсь создать простую программу, которая запускает другой процесс с использованием модуля subprocess в Python, и я хочу перехватить вывод процесса в реальном времени.

Я знаю, что это можно сделать так:

proc = subprocess.Popen(cmd, stdout=subprocess.PIPE)

for line in iter(proc.stdout.readline, ""):
    line = line.rstrip()
    if line != "":
        print(line)

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

Если я использую флаг universal_newlines в Popen, то я могу перехватить вывод, сгенерированный при возврате каретки, но я бы не знал, что это так, и мог печатать его только «регулярно» с новой строкой. Я хочу избежать этого, так как это может быть много выходных.

Мой вопрос в основном, могу ли я поймать вывод \r, как будто это \n, но отличить его от фактического \n вывода

EDIT

Вот упрощенный код того, что я пробовал:

Файл download.py:

import subprocess

try:
    subprocess.check_call(
        [
            "aws",
            "s3",
            "cp",
            "S3_LINK",
            "TARGET",
        ]
    )

except subprocess.CalledProcessError as err:
    print(err)
    raise SystemExit(1)

Файл process_runner.py:

import os
import sys

import subprocess

proc = subprocess.Popen(cmd, stdout=subprocess.PIPE)

for char in iter(lambda: proc.stdout.read(1), ""):
    sys.stdout.write(char)

Код в download использует aws s3 cp, что дает возврат каретки о ходе загрузки. Я хочу смоделировать это поведение вывода в моей программе process_runner, которая получает вывод download.

Сначала я попытался сделать вывод readline вместо read(1). Это не сработало из-за игнорирования ЧР.

1 Ответ

2 голосов
/ 24 июня 2019

Возможный способ - использовать двоичный интерфейс Popen, не указывая ни encoding, ни error и, конечно, не universal_newline. И затем мы можем использовать TextIOWrapper вокруг двоичного потока, с newline=''. Потому что документация для TextIOWrapper гласит:

... если символ новой строки None ... Если значение '', режим универсального перевода строки включен, но окончания строки возвращаются вызывающей стороне без перевода

(что соответствует PEP 3116)

Ваш исходный код может быть изменен на:

proc = subprocess.Popen(cmd, stdout=subprocess.PIPE)
out = io.TextIOWrapper(proc.stdout, newline='')

for line in out:
    # line is delimited with the universal newline convention and actually contains
    #  the original end of line, be it a raw \r, \n of the pair \r\n
    ...
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...