Итак, я столкнулся с проблемой использования подпроцесса для приложения на Python, которое я пишу. Чтобы проиллюстрировать проблему, я написал этот небольшой скрипт, который довольно хорошо копирует мою проблему.
from __future__ import print_function
import subprocess as sp
from select import select
p = sp.Popen(['ls'], stdout=sp.PIPE, stderr=sp.PIPE, stdin=sp.PIPE)
p.stdin.close()
while p.returncode is None or p.stdout.closed or p.stderr.closed:
# print('returncode is', p.returncode)
available_readers = select([p.stdout, p.stderr], [], [], 2.0)[0]
for r in available_readers:
print(r.read(1))
# output_display.insert(tk.END, r.read(1))
Конечно, мы все знаем, что команда ls
существует сразу после печати некоторых вещей в stdout
(или может быть stderr
), но вышеупомянутый скрипт никогда не существует.
Как видно из последней строки (комментария) в приведенном выше скрипте, я должен поместить содержимое подпроцесса в текстовый компонент tk. Поэтому я не могу использовать такие методы, как .communicate
и другие блокирующие вызовы, так как команда, которую мне нужно выполнить, занимает много времени, и мне нужно показывать вывод (почти) в реальном времени. (Конечно, я должен запустить это в отдельном потоке при запуске Tk, но это что-то другое).
Итак, я не могу понять, почему этот скрипт никогда не завершается. Он всегда печатает пустые строки (после ожидаемого вывода команды ls
).
Пожалуйста, сообщите. Я использую Python 2.6.6 на Ubuntu 10.10
Редактировать: вот версия вышеуказанного скрипта, которая работает
from __future__ import print_function
import subprocess as sp
from select import select
p = sp.Popen(['ls'], stdout=sp.PIPE, stderr=sp.PIPE, stdin=sp.PIPE)
p.stdin.close()
while p.poll() is None:
# print('returncode is', p.returncode)
available_readers = select([p.stdout, p.stderr], [], [], 2.0)[0]
for r in available_readers:
print(r.read(1), end='')
# output_display.insert(tk.END, r.read(1))
print(p.stdout.read(), end='')
print(p.stderr.read(), end='')