Я хочу вызвать внешний процесс из python. Процесс, который я вызываю, считывает входную строку и выдает токенизированный результат и ожидает другого ввода (двоичный файл — это токенизатор MeCab, если это помогает).
Мне нужно токенизировать тысячи строк строки, вызвав этот процесс.
Проблема в том, что Popen.communicate() работает, но ждет чтобы процесс умер до выдачи результата STDOUT. Я не хочу закрывать и открывать новые подпроцессы тысячи раз. (И я не хочу присылать весь текст, в будущем он легко может разрастись на десятки тысяч длинных строк.)
from subprocess import PIPE, Popen
with Popen("mecab -O wakati".split(), stdin=PIPE,
stdout=PIPE, stderr=PIPE, close_fds=False,
universal_newlines=True, bufsize=1) as proc:
output, errors = proc.communicate("foobarbaz")
print(output)
Я пробовал читать proc.stdout.read()
вместо использования сообщения но он заблокирован stdin
и не возвращает никаких результатов до proc.stdin.close()
вызывается. Что, опять же, означает, что мне нужно каждый раз создавать новый процесс.
Я пытался реализовать очереди и потоки из аналогичного вопроса, как показано ниже, но он либо ничего не возвращает, поэтому застревает на While True
, либо когда я принудительно заполняю буфер stdin путем повторной отправки строк, он выводит все результаты сразу .
from subprocess import PIPE, Popen
from threading import Thread
from queue import Queue, Empty
def enqueue_output(out, queue):
for line in iter(out.readline, b''):
queue.put(line)
out.close()
p = Popen('mecab -O wakati'.split(), stdout=PIPE, stdin=PIPE,
universal_newlines=True, bufsize=1, close_fds=False)
q = Queue()
t = Thread(target=enqueue_output, args=(p.stdout, q))
t.daemon = True
t.start()
p.stdin.write("foobarbaz")
while True:
try:
line = q.get_nowait()
except Empty:
pass
else:
print(line)
break
Также просмотрел маршрут Pexpect, но его порт Windows не поддерживает некоторые важные модули (на основе pty), поэтому я также не смог его применить.
Я знаю, что есть много похожих ответов, и я пробовал большинство из них. Но ничто из того, что я пробовал, не работает в Windows.
РЕДАКТИРОВАТЬ: некоторая информация о двоичном файле, который я использую, когда я использую его через командную строку. Он запускает и маркирует предложения, которые я даю, пока я не закончу и принудительно не закрою программу.
(...ожидание_ввода -> получение_ввода -> вывод -> ожидание_ввода...)
Спасибо.
wakati
, не можете ли вы просто передать все строки вашего ввода (переводы строк и все) в стандартный ввод процесса? - person Ahmed Fasih   schedule 24.03.2017FILE
с буферизацией по умолчанию, то pipedstdout
имеет буфер размером 4 КиБ. Пробовали ли вы повторно вводить данные, пока mecab не заполнит и не очистит свой буферstdout
? Есть ли в mecab параметр командной строки для принудительного использования без буферизации или буферизации строки вместо полной буферизации? - person Eryk Sun   schedule 24.03.2017FILE
потоками. Ситуация со временем выполнения C слишком сложна. Процесс может быть статически или динамически связан с одним или несколькими CRT. В Linux ситуация иная, поэтому есть такие команды, какstdbuf
, которые могут попытаться изменить буферизацию стандартныхFILE
потоков. - person Eryk Sun   schedule 24.03.2017