
I lost the original thread, but my first thought was to use the readline module's history capability to save and reload a "session". This hack partially works for what little testing I've done (place it in sitecustomize.py): import readline import os import sys _start_len = len(open(os.path.expanduser("~/.pyhist")).readlines()) _session_file = os.path.expanduser("~/.pysession") def save(f=_session_file, start=_start_len): sf = open(f, 'w') while True: line = readline.get_history_item(start) start += 1 if line is None: break if line.startswith('save(') or line.startswith('load('): continue sf.write(line+"\n") def load(f=_session_file): execfile(f, sys._getframe(-1).f_globals) import __builtin__ __builtin__.save = save __builtin__.load = load My readline history is stored in ~/.pyhist. I can't use readline.get_history_length() to mark the start of a session for reasons which are not obvious to me. When I first started futzing around with it, readline.get_history_length() returned 9934. Now, even though my ~/.pyhist file has more than 9960 lines, get_history_length() seems to always return -1, thus making it useless in this context. Here's a simple session showing save() and load() within the same session: >>> import math >>> print math.sin(47) 0.123573122745 >>> def f(): ... return math.sin(48) ... >>> save() >>> load() 0.123573122745 >>> f <function f at 0x431830> >>> f() -0.76825466132366682 Note that f may not be a new f, however. A call to load() in a fresh session fails to place 'f' in the session's globals. I'm not sure why. Any ideas? Skip

>> My readline history is stored in ~/.pyhist. I can't use >> readline.get_history_length() to mark the start of a session for >> reasons which are not obvious to me. Phillip> get_history_length() is the length you've set for truncation, Phillip> not the actual length. You want get_current_history_length(), Phillip> IIRC. Yes, thanks. I decided to dispense with accessing the "start" of the session and force the user to simply mark() where a session is to start. That's one extra function to remember, but seems a lot more flexible. Appended is my current incarnation. Still doesn't load() right, though save() seems to work. Usage is: mark() ... bunch of commands at the interpreter prompt ... save() Any clues about what I'm doing wrong in load()? I want to stuff the evaluated objects into the globals() of the caller (that is, the globals for the interactive session in most situations). Skip import readline import os import sys # needs to match the filename the user uses! _histfile = os.path.expanduser("~/.pyhist") # where we save sessions _session_file = os.path.expanduser("~/.pysession") # mark with something valid at the interpreter but unlikely to be executed # by the user _marker = '((1.0+999.0j, "mark", 999.0-1.0j))' def save(): end = readline.get_current_history_length() - 1 session = [] item = readline.get_history_item(end) while item != _marker: session.insert(0, item+"\n") end -= 1 item = readline.get_history_item(end) file(_session_file, 'w').writelines(session) print >> sys.stderr, "saved session to", _session_file def load(): execfile(_session_file, sys._getframe(-1).f_globals) print >> sys.stderr, "loaded session from", _session_file def mark(): readline.add_history(_marker) import __builtin__ __builtin__.save = save __builtin__.load = load __builtin__.mark = mark

"Phillip J. Eby" <pje@telecommunity.com>
What does getframe with a negative number do?
Obviously it uses the time machine to look into the future a little and return a frame that is *going* to be called from the current function... Greg Ewing, Computer Science Dept, +--------------------------------------+ University of Canterbury, | A citizen of NewZealandCorp, a | Christchurch, New Zealand | wholly-owned subsidiary of USA Inc. | greg@cosc.canterbury.ac.nz +--------------------------------------+

At 02:27 PM 12/2/03 +1300, Greg Ewing wrote:
Actually, it appears to return the same result as sys._getframe(0). Maybe it should raise an exception for a negative value. (OTOH, maybe leaving it so that it silently does something meaningless will help discourage people from using it so often... ;) )

>> > What does getframe with a negative number do? >> Obviously it uses the time machine to look into the future... Phillip> Maybe it should raise an exception for a negative value. Phillip> (OTOH, maybe leaving it so that it silently does something Phillip> meaningless will help discourage people from using it so Phillip> often... ;) ) Yeah, whatever. ;-) At any rate, now that Phillip and Tim straightened me out on my number line basics, there's a simple session save/restore available at http://www.musi-cal.com/~skip/python/save_session.py Making it work on Windows (where it's probably needed more) is left as an exercise for the reader. Skip

>> My readline history is stored in ~/.pyhist. I can't use >> readline.get_history_length() to mark the start of a session for >> reasons which are not obvious to me. Phillip> get_history_length() is the length you've set for truncation, Phillip> not the actual length. You want get_current_history_length(), Phillip> IIRC. Yes, thanks. I decided to dispense with accessing the "start" of the session and force the user to simply mark() where a session is to start. That's one extra function to remember, but seems a lot more flexible. Appended is my current incarnation. Still doesn't load() right, though save() seems to work. Usage is: mark() ... bunch of commands at the interpreter prompt ... save() Any clues about what I'm doing wrong in load()? I want to stuff the evaluated objects into the globals() of the caller (that is, the globals for the interactive session in most situations). Skip import readline import os import sys # needs to match the filename the user uses! _histfile = os.path.expanduser("~/.pyhist") # where we save sessions _session_file = os.path.expanduser("~/.pysession") # mark with something valid at the interpreter but unlikely to be executed # by the user _marker = '((1.0+999.0j, "mark", 999.0-1.0j))' def save(): end = readline.get_current_history_length() - 1 session = [] item = readline.get_history_item(end) while item != _marker: session.insert(0, item+"\n") end -= 1 item = readline.get_history_item(end) file(_session_file, 'w').writelines(session) print >> sys.stderr, "saved session to", _session_file def load(): execfile(_session_file, sys._getframe(-1).f_globals) print >> sys.stderr, "loaded session from", _session_file def mark(): readline.add_history(_marker) import __builtin__ __builtin__.save = save __builtin__.load = load __builtin__.mark = mark

"Phillip J. Eby" <pje@telecommunity.com>
What does getframe with a negative number do?
Obviously it uses the time machine to look into the future a little and return a frame that is *going* to be called from the current function... Greg Ewing, Computer Science Dept, +--------------------------------------+ University of Canterbury, | A citizen of NewZealandCorp, a | Christchurch, New Zealand | wholly-owned subsidiary of USA Inc. | greg@cosc.canterbury.ac.nz +--------------------------------------+

At 02:27 PM 12/2/03 +1300, Greg Ewing wrote:
Actually, it appears to return the same result as sys._getframe(0). Maybe it should raise an exception for a negative value. (OTOH, maybe leaving it so that it silently does something meaningless will help discourage people from using it so often... ;) )

>> > What does getframe with a negative number do? >> Obviously it uses the time machine to look into the future... Phillip> Maybe it should raise an exception for a negative value. Phillip> (OTOH, maybe leaving it so that it silently does something Phillip> meaningless will help discourage people from using it so Phillip> often... ;) ) Yeah, whatever. ;-) At any rate, now that Phillip and Tim straightened me out on my number line basics, there's a simple session save/restore available at http://www.musi-cal.com/~skip/python/save_session.py Making it work on Windows (where it's probably needed more) is left as an exercise for the reader. Skip
participants (3)
-
Greg Ewing
-
Phillip J. Eby
-
Skip Montanaro