2010-08-06 6 views
5

J'ai ce code qui fonctionne très bien en Python 2.5, mais pas 2.7:python 2.7/exec/quel est le problème?

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

Et je reçois:

 
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

commentaires mineurs: le style Pythonic est d'utiliser TitleCase pour les classes seulement, il devrait être 'captureExec' ou' capture_exec'. En outre, vous devriez attraper 'ImportError' dans le bloc' try ... except'. – katrielalex

Répondre

14

io.StringIO est source de confusion en Python 2.7 car il est backported des octets 3.x/monde de cordes. Ce code obtient la même erreur que le vôtre:

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

causes:

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

Si vous utilisez uniquement Python 2.x, puis passez le module io tout à fait, et le bâton avec StringIO. Si vous voulez vraiment utiliser io, changer votre importation:

from io import BytesIO as StringIO 
+0

+1 pour 'BytesIO'. Je pense que beaucoup de vieux code 2.x ne va pas être très compatible avec 2.7:/semble que 2.7 va être plus un tremplin vers 3.x –

2

Il est de mauvaises nouvelles

io.StringIO veut travailler avec unicode. Vous pourriez penser que vous pouvez y remédier en mettant un u devant la chaîne que vous souhaitez imprimer comme ce

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

cependant print est vraiment rompu pour cela car il provoque 2 écrit au StringIO. Le premier est u"hello world" ce qui est bien, mais il suit avec "\n"

donc au lieu vous devez écrire quelque chose comme ça

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