Capturing Interactive Output from Python Interpreter in Python
Everything has to be automated. As I’m writing a small book on Python, I have to update the version of the language every year :-D. With Python 3.1, the problem became more serious, because now I have to test the examples in the book with this new version that is not fully compatible. The book is being written in LaTeX, using TextMate and Skim on Mac OS X. I made a mistake by manually inserting the Python source code into the LaTeX text; now I have to review each script individually.
As I’m reviewing them, I’m also fixing them and this time saving the Python programs in separate files.
I decided to use SCONS to help with the task. For that, a custom builder needs to be created. In the SConstruct:
PYTHON_BIN="/opt/local/bin/python2.6"
python_output=Builder(action='$PYTHON_BIN capture.py $SOURCE $TARGET',
suffix = '.pyt',
src_suffix = '.py')
env = Environment(BUILDERS = {'python_output': python_output})
env["PYTHON_BIN"]=PYTHON_BIN
env.python_output("p1")
and then the Python program that does the capturing, capture.py:
import pexpect
import sys
PYTHON_BIN="/opt/local/bin/python3.1"
interacao = file(sys.argv[1], "r").readlines()
python = pexpect.spawn(PYTHON_BIN)
python.logfile_read = file(sys.argv[2], "w")
for l in interacao:
python.expect(['>>> ', '... '])
python.send(l)
python.sendline("exit()")
python.expect(pexpect.EOF)
The script capture.py receives two parameters: the name of the Python file and the name of the output file.
To test it, create a file p1.py:
a=5
b=10
print(a+b)
c = a + b
d = c * a / 100
print(c,d)
for x in range(3):
print ("Oi")
#Error:
=d=d
rrrrr
It should produce the following output in p1.pyt:
Python 3.1.1 (r311:74480, Oct 24 2009, 17:11:04)
[GCC 4.2.1 (Apple Inc. build 5646)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> a=5
>>> b=10
>>> print(a+b)
15
>>> c = a + b
>>> d = c * a / 100
>>> print(c,d)
15 0.75
>>> for x in range(3):
... print ("Oi")
...
Oi
Oi
Oi
>>> #Error:
... =d=d
File "", line 2
=d=d
^
SyntaxError: invalid syntax
>>> rrrrr
Traceback (most recent call last):
File "", line 1, in
NameError: name 'rrrrr' is not defined
>>>
>>> exit()
If you use this file, don’t forget to modify the PYTHON_PATH variables. I’m using MacPorts and I have to specify the full path of the Python version I want to use. This avoids problems with other versions installed on the system, such as Apple’s Python.
I hope this helps someone with a similar problem: capturing the interactive output from a program as if it were a common terminal.