How to obtain a 'interactive session' of a script?

B

Bo Peng

Dear list,

I have a long list of commands in the form of a script and would like to
obtain a log file as if I enter the commands one by one. (The output
will be used in a tutorial.) What would be the best way to do it? Copy
and paste is not acceptable since I make frequent changes tot he script.

Many thanks in advance.
Bo
 
F

Fredrik Lundh

Bo said:
I have a long list of commands in the form of a script and would like to
obtain a log file as if I enter the commands one by one. (The output
will be used in a tutorial.) What would be the best way to do it? Copy
and paste is not acceptable since I make frequent changes tot he script.

the first example on this page

http://effbot.org/librarybook/code.htm

shows how to execute Python code line by line.

here's a variation that echoes the script fragments with the right prompts
in front of them:

import code

SCRIPT = [line.rstrip() for line in open("myscript.py")]

script = ""
prompt = ">>>"

for line in SCRIPT:
print prompt, line
script = script + line + "\n"
co = code.compile_command(script, "<stdin>", "exec")
if co:
# got a complete statement. execute it!
exec co
script = ""
prompt = ">>>"
else:
prompt = "..."

</F>
 
J

jepler

The 'code' module contains 'Utilities needed to emulate Python's interactive
interpreter.'. By subclassing code.InteractiveConsole and replacing the
raw_input method with one which reads from a file, I think you can get what you
want.

The example below the classes uses StringIO so that it can be self-contained,
but you'll probably use a regular file instead.

import code, sys

class BoPeng(code.InteractiveConsole):
def __init__(self, locals=None, filename="<console>", file = None):
self.file = file or open(filename)
code.InteractiveConsole.__init__(self, locals, filename)

def raw_input(self, prompt):
l = self.file.readline()
if l == '': raise EOFError
sys.stdout.write(prompt + l)
return l.strip("\n")

session = '''\
print 3+3
for i in range(10):
print i

print "Example of a traceback:"
1/0
'''

import StringIO
b = BoPeng(file = StringIO.StringIO(session))
b.interact(None)

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.2.6 (GNU/Linux)

iD8DBQFDLYekJd01MZaTXX0RAnf4AKCU84FVVK+2pgx3yQS5IBQcoK6wwACgmMaM
8zYxjYispPtHhknnges00UE=
=yUXD
-----END PGP SIGNATURE-----
 
B

Bo Peng

Thank you for the suggestions and code!
import code

SCRIPT = [line.rstrip() for line in open("myscript.py")]

script = ""
prompt = ">>>"

for line in SCRIPT:
print prompt, line
script = script + line + "\n"
co = code.compile_command(script, "<stdin>", "exec")
if co:
# got a complete statement. execute it!
exec co
script = ""
prompt = ">>>"
else:
prompt = "..."

This one fails at function definition.

def fun():
a=1
b=2 <--- not included.

Still trying other methods.
Bo
 
B

Bo Peng

The 'code' module contains 'Utilities needed to emulate Python's interactive
interpreter.'. By subclassing code.InteractiveConsole and replacing the
raw_input method with one which reads from a file, I think you can get what you
want.

This method works fine with only one minor problem. It would stop
(waiting for user input) at help(str) command. I will have to find a way
to feed the program with'q' etc.

Bo
 
F

Fredrik Lundh

Bo said:
import code

SCRIPT = [line.rstrip() for line in open("myscript.py")]

script = ""
prompt = ">>>"

for line in SCRIPT:
print prompt, line
script = script + line + "\n"
co = code.compile_command(script, "<stdin>", "exec")
if co:
# got a complete statement. execute it!
exec co
script = ""
prompt = ">>>"
else:
prompt = "..."

This one fails at function definition.

def fun():
a=1
b=2 <--- not included.

hmm. looks like a bug in compile_command. stripping off the trailing
newline seems to fix it:

co = code.compile_command(script[:-1], "<stdin>", "exec")

(to make things look right, you need to add an empty line after each
function definition in your code)

</F>
 
F

Fredrik Lundh

Bo said:
This method works fine with only one minor problem. It would stop
(waiting for user input) at help(str) command. I will have to find a way
to feed the program with'q' etc.

replacing sys.stdin with something that isn't a TTY will fix this.

here's one way to do it:

class wrapper:
def __init__(self, file):
self.file = file
def isatty(self):
return 0
def __getattr__(self, key):
return getattr(self.file, key)

sys.stdin = wrapper(sys.stdin)

</F>
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,264
Messages
2,571,321
Members
48,004
Latest member
KelseyFors

Latest Threads

Top