I'm using a strategy based around os.dup2 (similar to examples on this site) to redirect C/fortran level output into a temporary file for capturing.
The only problem I've noticed is, if you use this code from an interactive shell in windows (either python.exe or ipython) it has the strange side effect of enabling output buffering in the console.
Before capture sys.stdout
is some kind of file object that returns True
for istty()
. Typing print('hi')
causes hi to be output directly.
After capture sys.stdout
points to exactly the same file object but print('hi')
no longer shows anything until sys.stdout.flush()
is called.
Below is a minimal example script "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()
Opening a command prompt and running the script works fine. This produces the expected output:
python.exe test.py
Running it from a python shell does not:
python.exe
>>> import test.py
>>> test.run()
>>> print('hello?')
No output is shown until stdout is flushed:
>>> import sys
>>> sys.stdout.flush()
Does anybody have any idea what's going on?
Quick info:
- The issue appears on Windows, not on linux (so probably not on mac).
- Same behaviour in both Python 2.7.6 and Python 2.7.9
- The script should capture C/fortran output, not just python output
- It runs without errors on windows, but afterwards print() no longer flushes