Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

capturing dis.dis results

Is there any way to get the output of dis.dis() without redirecting sys.stdout? I have tried:

out=str(dis.dis())

and

out=""""""
out+=str(dis.dis())

However I soon found out that it returns None. Is there any way to fix this?

like image 538
IT Ninja Avatar asked Aug 24 '12 14:08

IT Ninja


1 Answers

Unfortunately, in Python versions before 3.4 the dis module uses print statements to stdout, so it won't return anything directly useful. Either you have to re-implement the dis, disassemble and disassemble_string functions, or you temporarily replace sys.stdout with an alternative to capture the output:

import sys
from cStringIO import StringIO

out = StringIO()
stdout = sys.stdout
sys.stdout = out
try:
    dis.dis()
finally:
    sys.stdout = stdout
out = out.getvalue()

This is actually best done using a context manager:

import sys
from contextlib import contextmanager
from cStringIO import StringIO

@contextmanager
def captureStdOut(output):
    stdout = sys.stdout
    sys.stdout = output
    try:
        yield
    finally:
        sys.stdout = stdout

out = StringIO()
with captureStdOut(out):
    dis.dis()
print out.getvalue()

That way you are guaranteed to have stdout restored even if something goes wrong with dis. A little demonstration:

>>> out = StringIO()
>>> with captureStdOut(out):
...     dis.dis(captureStdOut)
... 
>>> print out.getvalue()
 83           0 LOAD_GLOBAL              0 (GeneratorContextManager)
              3 LOAD_DEREF               0 (func)
              6 LOAD_FAST                0 (args)
              9 LOAD_FAST                1 (kwds)
             12 CALL_FUNCTION_VAR_KW     0
             15 CALL_FUNCTION            1
             18 RETURN_VALUE        

In Python 3.4 and up, the relevant functions take a file parameter to redirect output to:

from io import StringIO

with StringIO() as out:
    dis.dis(file=out)
    print(out.getvalue())
like image 64
Martijn Pieters Avatar answered Oct 18 '22 20:10

Martijn Pieters