在python中,你可以使用exec()更快地执行compile()字符串。但是一旦我使用它,我们就会在exec中发生异常时丢失信息。
例如,这是一个调用未知方法的代码片段(用于演示目的):
code = 'my_unknown_method()'
bytecode = compile(code, '<string>', 'exec')
后来,我在那个字节码上调用exec:
exec bytecode
回溯显示:
Traceback (most recent call last):
File "test.py", line 3, in <module>
exec bytecode
File "<string>", line 1, in <module>
NameError: name 'my_unknown_method' is not defined
“exec()”框架现在模糊不清。我希望有一个更好的例外:
Traceback (most recent call last):
File "test.py", line 3, in <module>
exec "my_unknown_method()"
File "<string>", line 1, in <module>
NameError: name 'my_unknown_method' is not defined
有什么想法吗?
注意:
EDIT2:我查了一些jinja2调试代码,他们也在重写回溯,但不是内容。除了钩子我需要一个自定义吗?我对它的关注是因为它不在回溯本身,如果用户/模块/任何异常,回溯将不包含有价值的信息。
答案 0 :(得分:3)
你应该看看Armin Ronacher的this talk。他是Jinja2的作者,他在演讲中解释了他如何操纵Jinja2中的堆栈痕迹。如果我没记错的话,他正在使用ctypes来操纵Python的C级数据结构。在我看来,谈话是顺便提一下整个Europython 2011的最佳话题。
答案 1 :(得分:2)
经过深入搜索,这是不可能的,CPython正在使用自己的API来确定文件的位置等,并且它不能用纯Python修补。
答案 2 :(得分:0)
这样的事情怎么样:
import sys
def mkexec(code_str):
bc = compile(code, '<string>', 'exec')
def run():
try:
exec bc
except: # Yes I know a bare except
t, v, tb = sys.exc_info()
raise MyUsefullException("%s raised %s" % (code_str, v))
return run
exe = mkexec("some_unknown_something()")
exe()