dis.dis question

Bengt Richter bokr at oz.net
Sat Oct 15 21:47:19 EDT 2005


On Sun, 09 Oct 2005 12:10:46 GMT, Ron Adam <rrr at ronadam.com> wrote:

>Ron Adam wrote:
>> 
>> Can anyone show me an example of of using dis() with a traceback?
>> 
>> Examples of using disassemble_string() and distb() separately if 
>> possible would be nice also.
>
>  [cliped]
>
>> But I still need to rewrite disassemble_string() and need to test it 
>> with tracebacks.
>> 
>> Cheers,
>> Ron
>
>It seems I've found a bug in dis.py, or maybe a expected non feature. 
>When running dis from a program it fails to find the last traceback 
>because sys.last_traceback doesn't get set.  (a bug in sys?)  It works 
>ok from the shell, but not from the program.
>
>Changing it to to get sys.exc_info()[2], fix's it in a program, but then 
>it doesn't work in the shell.  So I replaced it with the following which 
>works in both.
>
>         try:
>             if hasattr(sys,'last_traceback'):
>                 tb = sys.last_traceback
>             else:
>                 tb = sys.exc_info()[2]
>         except AttributeError:
>             raise RuntimeError, "no last traceback to disassemble"
>
>I'm still looking for info on how to use disassemble_string().
>

One way to get dis output without modufying dis is to capture stdout:
(ancient thing I cobbled together, no guarantees ;-)

 >>> class SOCapture:
 ...     """class to capture stdout between calls to start & end methods, q.v."""
 ...     import sys
 ...     def __init__(self):
 ...         self.so = self.sys.stdout
 ...         self.text = []
 ...     def start(self, starttext=None):
 ...         """Overrides sys.stdout to capture writes.
 ...         Optional starttext is immediately appended as if written to stdout."""
 ...         self.sys.stdout = self
 ...         if starttext is None: return
 ...         self.text.append(starttext)
 ...     def end(self, endtext=None):
 ...         """Restores stdout to value seen at contruction time.
 ...         Optional endtext is appended as if written to stdout before that."""
 ...         self.sys.stdout = self.so
 ...         if endtext is None: return
 ...         self.text.append(endtext)
 ...     def gettext(self):
 ...         """Returns captured text as single string."""
 ...         return ''.join(self.text)
 ...     def clear(self):
 ...         """Clears captured text list."""
 ...         self.text = []
 ...     def write(self, s):
 ...         """Appends written string to captured text list.
 ...         This method is what allows an instance to stand in for stdout."""
 ...         self.text.append(s)
 ...
 >>> def foo(x): return (x+1)**2
 ...
 >>> so = SOCapture()
 >>> import dis
 >>> so.start()
 >>> dis.dis(foo)
 >>> so.end()
 >>> print so.gettext()
   1           0 LOAD_FAST                0 (x)
               3 LOAD_CONST               1 (1)
               6 BINARY_ADD
               7 LOAD_CONST               2 (2)
              10 BINARY_POWER
              11 RETURN_VALUE

Or safer:

 >>> def diss(code):
 ...     try:
 ...         so = SOCapture()
 ...         so.start()
 ...         dis.dis(code)
 ...     finally:
 ...         so.end()
 ...         return so.gettext()
 ...
 >>> diss(foo)
 '  1           0 LOAD_FAST                0 (x)\n              3 LOAD_CONST               1 (1)\
 n              6 BINARY_ADD          \n              7 LOAD_CONST               2 (2)\n
     10 BINARY_POWER        \n             11 RETURN_VALUE        \n'
 >>> print diss(foo)
   1           0 LOAD_FAST                0 (x)
               3 LOAD_CONST               1 (1)
               6 BINARY_ADD
               7 LOAD_CONST               2 (2)
              10 BINARY_POWER
              11 RETURN_VALUE


Regards,
Bengt Richter



More information about the Python-list mailing list