Я пытаюсь получить вывод полноэкранной программы терминалов, которая использует перерисовки эвакуационных кодов для представления данных и для чего требуется tty
(или pty
).
Основная процедура, которой должен следовать человек:
- Запустите программу в терминале.
- Программа использует перерисовку для отображения и обновления различных полей данных.
- Человек ждет, пока дисплей не будет согласован (возможно, используя такие сигналы, как "он не мерцает" или "он равен 0,5 с момента последнего обновления" ).
- Человек смотрит на поля в определенных положениях и запоминает или записывает данные.
- Человек выходит из программы.
- Затем человек выполняет действия вне программы на основе этих данных.
Я хотел бы автоматизировать этот процесс. Шаги 4 и 5 могут быть выполнены в любом порядке. Хотя перфекционист во мне беспокоится о самосогласованности состояния экрана, я признаю, что я не уверен, как правильно его определить (кроме, быть может, использовать "это был больше, чем определенный период времени с момента последнего обновления" ).
Похоже, что использование pty
и subprocess
, за которым следует какой-то экранный скребок, является одним из возможных способов сделать это, но я не совсем понимаю, как использовать их все вместе, и какие опасности существуют с некоторыми из объекты нижнего уровня, которые я использую.
Рассмотрим эту программу:
#!/usr/bin/env python2
import os
import pty
import subprocess
import time
import pexpect.ANSI
# Psuedo-terminal FDs
fd_master, fd_slave = pty.openpty()
# Start 'the_program'
the_proc = subprocess.Popen(['the_program'], stdin=fd_master, stdout=fd_slave, stderr=fd_slave)
# Just kill it after a couple of seconds
time.sleep(2)
the_proc.terminate()
# Read output into a buffer
output_buffer = b''
read_size = None
while (read_size is None) or (read_size > 0):
chunk = os.read(fd_master, 1024)
output_buffer += chunk
read_size = len(chunk)
print("output buffer size: {:d}".format(len(output_buffer)))
# Feed output to screen scraper
ansi_term = pexpect.ANSI.ANSI(24, 80)
ansi_term.write(output_buffer)
# Parse presented data...
Одна проблема заключается в том, что блоки вызовов os.read()
всегда. Мне также интересно, есть ли лучший способ получить выход pty
для дальнейшего использования. В частности:
- Есть ли способ сделать это (или его части) с помощью кода более высокого уровня? Я не могу просто использовать
subprocess.PIPE
для моего вызоваPopen
, потому что тогда целевая программа не будет работать. Но могу ли я обернуть эти дескрипторы файлов чем-то более удобными способами для ввода/вывода? - Если нет, как мне избежать блокировки во время вызова
os.read
? Я больше привык к файлоподобным объектам, гдеread()
всегда возвращает, и просто возвращает пустую строку, если конец потока достигнут. Здесьos.read
в конечном итоге блокирует независимо от того, что. - Я опасаюсь заставить этот script "просто работать", не осознавая потенциальных опасностей (например, условия гонки, которые появляются один раз в тысячу). Что еще мне нужно знать?
Я также открываю мысль, что использование pty
и subprocess
в первую очередь не лучший способ сделать это.