2010-08-06 36 views
5

tôi có mã này chạy tốt trong Python 2.5 nhưng không phải trong 2,7:python 2.7/exec/có gì sai?

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

Và tôi nhận được:

 
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

ý kiến ​​nhỏ: phong cách Pythonic là sử dụng TitleCase cho các lớp học mà thôi, nó phải được 'captureExec' hoặc' capture_exec'. Ngoài ra, bạn nên đặc biệt nắm bắt 'ImportError' trong khối' try ... except'. – katrielalex

Trả lời

14

io.StringIO là khó hiểu trong Python 2.7 vì nó backported từ các byte 3.x/chuỗi thế giới. Mã này được các lỗi tương tự như của bạn:

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

nguyên nhân:

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

Nếu bạn chỉ sử dụng Python 2.x, sau đó bỏ qua các mô-đun io hoàn toàn, và gắn bó với StringIO. Nếu bạn thực sự muốn sử dụng io, thay đổi khẩu của bạn để:

from io import BytesIO as StringIO 
+0

+1 cho 'BytesIO'. Tôi nghĩ rằng rất nhiều mã 2.x cũ sẽ không tương thích với 2.7:/Có vẻ như 2.7 sẽ có nhiều bước đệm hơn 3.x –

2

Đó là tin xấu

io.StringIO muốn làm việc với unicode. Bạn có thể nghĩ rằng bạn có thể sửa chữa nó bằng cách đặt một u ở phía trước của chuỗi bạn muốn in như thế này

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

tuy nhiên print thực sự bị phá vỡ cho điều này vì nó gây ra 2 viết cho tín hữu StringIO. Người đầu tiên là u"hello world" đó là tốt, nhưng sau đó nó sau với "\n"

nên thay vì bạn cần phải viết một cái gì đó như thế này

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