2010-08-06 4 views
5

Ich habe diesen Code, der in Python 2.5 Fein läuft aber nicht in 2.7:Python 2.7/exec/was ist los?

import sys 
import traceback 
try: 
    from io import StringIO 
except: 
    from StringIO import StringIO 

def CaptureExec(stmt): 
    oldio = (sys.stdin, sys.stdout, sys.stderr) 
    sio = StringIO() 
    sys.stdout = sys.stderr = sio 
    try: 
     exec(stmt, globals(), globals()) 
     out = sio.getvalue() 
    except Exception, e: 
     out = str(e) + "\n" + traceback.format_exc() 
    sys.stdin, sys.stdout, sys.stderr = oldio 
    return out 

print "%s" % CaptureExec(""" 
import random 
print "hello world" 
""") 

Und ich bekomme:

 
string argument expected, got 'str' 
Traceback (most recent call last): 
    File "D:\3.py", line 13, in CaptureExec 
    exec(stmt, globals(), globals()) 
    File "", line 3, in 
TypeError: string argument expected, got 'str' 
+2

Minor Kommentare schreiben: Pythonic Stil ist nur Titlecase für Klassen zu verwenden, sollte es sein 'captureExec' oder' capture_exec'. Außerdem sollten Sie 'ImportError' im' try ... except' Block abfangen. – katrielalex

Antwort

14

io.StringIO in Python 2.7 verwirrend ist, weil es von dem 3.x Bytes zurückportiert ist/String-Welt. Dieser Code wird den gleichen Fehler wie bei Ihnen:

from io import StringIO 
sio = StringIO() 
sio.write("Hello\n") 

Ursachen:

Traceback (most recent call last): 
    File "so2.py", line 3, in <module> 
    sio.write("Hello\n") 
TypeError: string argument expected, got 'str' 

Wenn Sie nur 2.x Python verwenden, dann das io Modul ganz überspringen, und bleiben StringIO. Wenn Sie wirklich verwenden io wollen, ändern Sie Ihre Import:

from io import BytesIO as StringIO 
+0

+1 für 'BytesIO'. Ich denke, viele alte 2.x-Code wird nicht sehr kompatibel mit 2.7 sein:/Scheint wie 2.7 wird mehr ein Sprungbrett zu 3.x sein –

2

Es ist eine schlechte Nachricht

io.StringIO will mit Unicode arbeiten. Man könnte denken, Sie es, indem man ein u vor dem String beheben können Sie dieses

print "%s" % CaptureExec(""" 
import random 
print u"hello world" 
""") 

jedoch print drucken möchten ist dies wirklich gebrochen, wie es verursacht 2 zum StringIO schreibt. Die erste ist u"hello world" was in Ordnung ist, aber dann folgt es mit "\n"

so stattdessen müssen Sie so etwas wie diese

print "%s" % CaptureExec(""" 
import random 
sys.stdout.write(u"hello world\n") 
""")