Next topic

This Page

Quick search

#!/usr/bin/env python"""Multithreaded interactive interpreter with GTK and Matplotlib support.WARNING:As of 2010/06/25, this is not working, at least on Linux.I have disabled it as a runnable script. - EFUsage: pyint-gtk.py -> starts shell with gtk thread running separately pyint-gtk.py -pylab [filename] -> initializes matplotlib, optionally running the named file. The shell starts after the file is executed.Threading code taken from:http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/65109, by BrianMcErlean and John Finlay.Matplotlib support taken from interactive.py in the matplotlib distribution.Also borrows liberally from code.py in the Python standard library."""from__future__importprint_function__author__="Fernando Perez <Fernando.Perez@colorado.edu>"importsysimportcodeimportthreadingimportgobjectimportgtktry:importreadlineexceptImportError:has_readline=Falseelse:has_readline=TrueclassMTConsole(code.InteractiveConsole):"""Simple multi-threaded shell"""def__init__(self,on_kill=None,*args,**kw):code.InteractiveConsole.__init__(self,*args,**kw)self.code_to_run=Noneself.ready=threading.Condition()self._kill=Falseifon_killisNone:on_kill=[]# Check that all things to kill are callable:for_inon_kill:ifnotcallable(_):raiseTypeError,'on_kill must be a list of callables'self.on_kill=on_kill# Set up tab-completerifhas_readline:importrlcompletertry:# this form only works with python 2.3self.completer=rlcompleter.Completer(self.locals)except:# simpler for py2.2self.completer=rlcompleter.Completer()readline.set_completer(self.completer.complete)# Use tab for completionsreadline.parse_and_bind('tab: complete')# This forces readline to automatically print the above list when tab# completion is set to 'complete'.readline.parse_and_bind('set show-all-if-ambiguous on')# Bindings for incremental searches in the history. These searches# use the string typed so far on the command line and search# anything in the previous input history containing them.readline.parse_and_bind('"\C-r": reverse-search-history')readline.parse_and_bind('"\C-s": forward-search-history')defrunsource(self,source,filename="<input>",symbol="single"):"""Compile and run some source in the interpreter. Arguments are as for compile_command(). One several things can happen: 1) The input is incorrect; compile_command() raised an exception (SyntaxError or OverflowError). A syntax traceback will be printed by calling the showsyntaxerror() method. 2) The input is incomplete, and more input is required; compile_command() returned None. Nothing happens. 3) The input is complete; compile_command() returned a code object. The code is executed by calling self.runcode() (which also handles run-time exceptions, except for SystemExit). The return value is True in case 2, False in the other cases (unless an exception is raised). The return value can be used to decide whether to use sys.ps1 or sys.ps2 to prompt the next line. """try:code=self.compile(source,filename,symbol)except(OverflowError,SyntaxError,ValueError):# Case 1self.showsyntaxerror(filename)returnFalseifcodeisNone:# Case 2returnTrue# Case 3# Store code in self, so the execution thread can handle itself.ready.acquire()self.code_to_run=codeself.ready.wait()# Wait until processed in timeout intervalself.ready.release()returnFalsedefruncode(self):"""Execute a code object. When an exception occurs, self.showtraceback() is called to display a traceback."""self.ready.acquire()ifself._kill:print('Closing threads...')sys.stdout.flush()fortokillinself.on_kill:tokill()print('Done.')ifself.code_to_runisnotNone:self.ready.notify()code.InteractiveConsole.runcode(self,self.code_to_run)self.code_to_run=Noneself.ready.release()returnTruedefkill(self):"""Kill the thread, returning when it has been shut down."""self.ready.acquire()self._kill=Trueself.ready.release()classGTKInterpreter(threading.Thread):"""Run gtk.main in the main thread and a python interpreter in a separate thread. Python commands can be passed to the thread where they will be executed. This is implemented by periodically checking for passed code using a GTK timeout callback. """TIMEOUT=100# Millisecond interval between timeouts.def__init__(self,banner=None):threading.Thread.__init__(self)self.banner=bannerself.shell=MTConsole(on_kill=[gtk.main_quit])defrun(self):self.pre_interact()self.shell.interact(self.banner)self.shell.kill()defmainloop(self):self.start()gobject.timeout_add(self.TIMEOUT,self.shell.runcode)try:ifgtk.gtk_version[0]>=2:gtk.gdk.threads_init()exceptAttributeError:passgtk.main()self.join()defpre_interact(self):"""This method should be overridden by subclasses. It gets called right before interact(), but after the thread starts. Typically used to push initialization code into the interpreter"""passclassMatplotLibInterpreter(GTKInterpreter):"""Threaded interpreter with matplotlib support. Note that this explicitly sets GTKAgg as the backend, since it has specific GTK hooks in it."""def__init__(self,banner=None):banner="""\nWelcome to matplotlib, a MATLAB-like python environment. help(matlab) -> help on matlab compatible commands from matplotlib. help(plotting) -> help on plotting commands. """GTKInterpreter.__init__(self,banner)defpre_interact(self):"""Initialize matplotlib before user interaction begins"""push=self.shell.push# Code to execute in user's namespacelines=["import matplotlib","matplotlib.use('GTKAgg')","matplotlib.interactive(1)","import matplotlib.pylab as pylab","from matplotlib.pylab import *\n"]map(push,lines)# Execute file if given.iflen(sys.argv)>1:importmatplotlibmatplotlib.interactive(0)# turn off interactionfname=sys.argv[1]try:inFile=file(fname,'r')exceptIOError:print('*** ERROR *** Could not read file <%s>'%fname)else:print('*** Executing file <%s>:'%fname)forlineininFile:ifline.lstrip().find('show()')==0:continueprint('>>',line)push(line)inFile.close()matplotlib.interactive(1)# turn on interactionif__name__=='__main__':print("This demo is not presently functional, so running")print("it as a script has been disabled.")sys.exit()# Quick sys.argv hack to extract the option and leave filenames in sys.argv.# For real option handling, use optparse or getopt.iflen(sys.argv)>1andsys.argv[1]=='-pylab':sys.argv=[sys.argv[0]]+sys.argv[2:]MatplotLibInterpreter().mainloop()else:GTKInterpreter().mainloop()