Я использую стратегию, основанную на os.dup2 (аналогично примерам на этом сайте), чтобы перенаправить вывод уровня C/fortran во временный файл для захвата.
Единственная проблема, которую я заметил, заключается в том, что если вы используете этот код из интерактивной оболочки в Windows (либо python.exe, либо ipython), он имеет странный побочный эффект включение буферизации вывода в консоли.
Перед захватом sys.stdout
находится какой-то файловый объект, который возвращает True
вместо istty()
. Ввод print('hi')
вызывает прямой вывод hi. После захвата sys.stdout
указывает точно на тот же файловый объект, но print('hi')
больше ничего не показывает, пока не будет вызван sys.stdout.flush()
.
Ниже приведен минимальный пример скрипта «test.py».
import os, sys, tempfile
class Capture(object):
def __init__(self):
super(Capture, self).__init__()
self._org = None # Original stdout stream
self._dup = None # Original system stdout descriptor
self._file = None # Temporary file to write stdout to
def start(self):
self._org = sys.stdout
sys.stdout = sys.__stdout__
fdout = sys.stdout.fileno()
self._file = tempfile.TemporaryFile()
self._dup = None
if fdout >= 0:
self._dup = os.dup(fdout)
os.dup2(self._file.fileno(), fdout)
def stop(self):
sys.stdout.flush()
if self._dup is not None:
os.dup2(self._dup, sys.stdout.fileno())
os.close(self._dup)
sys.stdout = self._org
self._file.seek(0)
out = self._file.readlines()
self._file.close()
return out
def run():
c = Capture()
c.start()
os.system('echo 10')
print('20')
x = c.stop()
print(x)
if __name__ == '__main__':
run()
Открытие командной строки и запуск скрипта работает нормально. Это дает ожидаемый результат:
python.exe test.py
Запуск его из оболочки Python не:
python.exe
>>> import test.py
>>> test.run()
>>> print('hello?')
Вывод не отображается, пока стандартный вывод не очищен:
>>> import sys
>>> sys.stdout.flush()
Кто-нибудь знает, что происходит?
Краткая информация:
- Проблема возникает в Windows, не в Linux (поэтому, вероятно, не на Mac).
- Такое же поведение как в Python 2.7.6, так и в Python 2.7.9.
- Сценарий должен захватывать вывод C/fortran, а не только вывод python.
- Он работает без ошибок в Windows, но после этого print() больше не сбрасывается