#python #python-3.x #shell #subprocess
#python #python-3.x #оболочка #подпроцесс
Вопрос:
Программа, которую я пытаюсь запустить с помощью команды оболочки, выводит одно слово в секунду. Я пытаюсь выполнить команду оболочки в скрипте Python и получить вывод в реальном времени для каждого выводимого слова. Все другие решения, которые я нашел в Интернете, на самом деле не печатают вывод в реальном времени, а скорее одну готовую строку за раз. Я хочу получить реальный вывод в реальном времени, где каждое слово печатается в реальном времени, а не в каждой строке. Это код, который я пробовал:
cmd=['slowprogram','-m', '15', '-l', '50']
p = subprocess.Popen(cmd, stdout=subprocess.PIPE, bufsize=1)
for line in iter(p.stdout.readline, b''):
print(line),
p.stdout.close()
p.wait()
Он ждет, пока не будет завершена одна строка, и печатает ее. Есть ли способ получать обновления и печатать каждое слово в строке в режиме реального времени?
Обновить:
p = subprocess.Popen(cmd, stdout=subprocess.PIPE, bufsize=1)
for line in iter(p.stdout.readline, b''):
for word in iter(line):
print(word)
p.stdout.close()
p.wait()
по какой-то причине возвращает кучу чисел…:
111
117
108
100
32
104
97
118
101
32
115
97
Как я могу получить каждое слово из строки?
Комментарии:
1.
p.stdout
это ввод-вывод. Объект BytesIO; синтаксически вы можете читать из него все, что хотите, как будто это файл. Возможно, вы также захотите изучитьbufsize
аргумент в зависимости от ваших потребностей.2. @YiFei Я попытался повторить каждое слово в строке, но результат был неожиданным. Я обновил свой вопрос, не могли бы вы взглянуть?
3. @YiFei я все еще не могу понять это. Не могли бы вы показать, как читать p.stdout в реальном времени?
Ответ №1:
Это один из способов сделать это, и он работал для меня в оболочке Linux. Он использует небуферизованный объект ввода-вывода и выводит по одному символу за раз. Я совершенно уверен, что есть лучшие способы, поскольку я не специалист по subprocess
обработке событий or. Возможно, вы также захотите изучить asyncio
.
with subprocess.Popen(cmd, stdout=subprocess.PIPE, bufsize=0) as p:
char = p.stdout.read(1)
while char != b'':
print(char.decode('UTF-8'), end='', flush=True)
char = p.stdout.read(1)
Комментарии:
1. Как я могу сохранить вывод в массив без ‘b’ перед каждым словом? Когда я добавляю переменную char в массив, перед каждым словом отображается ‘b’.
2. Перефразируя: как я могу сохранить весь вывод в массив?
3. Небольшой контекст: Python имеет дело с двумя типами «строк»: строкой байтов и строкой «текста». То, что мы получаем
Popen
, — это строка байтов и, следовательноb
, . Теперь байтовые строки могут быть преобразованы в текстовые строки путем декодирования и обратно путем кодирования.4. Я понимаю. Когда я пытаюсь сохранить декодированные символы в массив, мои слова по какой-то причине разделяются. ’Hello’ может превратиться в ’hel’ и ’lo’. Есть ли способ сохранить весь вывод без повторного запуска всей команды?
5. Допустим, у вас есть список (или любой итерируемый, если на то пошло)
L = ['hel', 'lo']
, который вы можете использовать''.join(L)
. Но в зависимости от ваших потребностей вы также можете сохранить и добавить к строке с самого начала.