2012-08-24 19 views
12

Esiste un modo per ottenere l'output di dis.dis() senza reindirizzare sys.stdout? Ho provato:acquisizione di risultati dis.dis

out=str(dis.dis()) 

e

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

Tuttavia ben presto ho scoperto che restituisce None. C'è un modo per risolvere questo problema?

+0

Perché non si desidera reindirizzare stdout (temporaneamente), come in [questa domanda] (http://stackoverflow.com/questions/1218933/can-i-redirect-the-stdout-in-python-into-some-sort-of-string-buffer)? –

+0

Per Python 3.4 o versioni successive, esistono altre soluzioni. Vedi [questa domanda] (http://stackoverflow.com/q/31347044/3004881). –

risposta

21

Sfortunatamente, nelle versioni Python precedenti al 3.4 il modulo dis utilizza le istruzioni di stampa sullo stdout, quindi non restituirà nulla di direttamente utile. O si deve ri-implementare le funzioni dis, disassemble e disassemble_string, o si sostituisce temporaneamente sys.stdout con un'alternativa di catturare l'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() 

Questo in realtà è meglio farlo attraverso un gestore di contesto:

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() 

In questo modo è garantito il ripristino di stdout anche se qualcosa va storto con dis. Una piccola dimostrazione:

>>> 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 e fino, le relative funzioni prendono un parametro file per reindirizzare l'output:

from io import StringIO 

with StringIO() as out: 
    dis.dis(file=out) 
    print(out.get_value()) 
+0

(+1): Usare il gestore di contesto qui è geniale. Bellissimo. – mgilson

+0

Non penso che sia necessario salvare 'sys.stdout' nella maggior parte dei casi, puoi semplicemente ripristinarlo usando' sys._stdout'. – agf

+0

@agf: presume che 'sys.stdout' non sia già stato sostituito.' Sys .__ stdout__' è il valore * predefinito * per 'sys.stdout' ma ciò non significa che' sys.stdout' è * attualmente * impostato su quel valore. –