如何重写回溯中的特定帧?
在Python中,你可以使用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
有什么想法吗?
注意:
- 我不想使用
- 我已经测试过的编译的第二个参数(文件名)来使用框架上的检查和修改 f_code,但它是只读属性。
编辑:在查看更多 sys.excepthook 后,我在 python 源代码/traceback.c 中看到,当 python 想要显示行内容时,它们是直接 fopen() 找到的文件。根本没有可用的钩子来显示我们自己的内容。唯一的方法是在磁盘上创建真实的假文件名?有人吗?
EDIT2:我检查了一些 jinja2 调试代码,他们也在重写回溯,但不是内容。我需要一个自定义的钩子除外吗?我对此的担忧是,因为它不在回溯本身中,如果用户/模块/任何内容出现异常,回溯将不会包含有价值的信息。
In python you can compile() string to be executed faster with exec(). But as soon as i use it, we lost information when an exception happen in the exec.
For example, here is a code snippet that calling a unknown method (for demo purposes):
code = 'my_unknown_method()'
bytecode = compile(code, '<string>', 'exec')
And later, i'm calling exec on that bytecode:
exec bytecode
The traceback showed is:
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
The "exec()" frame is now obscure. I would like to have a better exception like:
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
Any thoughts ?
Notes:
- I don't want to use the second argument of compile (the filename)
- I have tested to play with inspect and modify f_code on the frame, but it's readonly attribute.
EDIT: after looking more to sys.excepthook, i've seen that in python source code/traceback.c, when python want to show the line content, they are fopen() directly the file if found. No hook available at all to display our own content. The only way would be to create in real fake filename on disk ? Anyone ?
EDIT2: i checked some jinja2 debug code, and they are rewriting traceback too, but not for content. Would i need a custom except hook ? My concerns with it is since it's not in the traceback itself, if an user/module/whatever take the exception, the traceback will not contain valuable information.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
经过深入搜索,这是不可能的,CPython正在使用自己的API来确定文件的位置等,并且无法在纯Python中进行修补。
After a deep search, it's not possible, CPython is using its own API to determine where the file is etc, and it cannot be patched in pure Python.
像这样的事情怎么样:
How about something like this:
您应该看看 Armin Ronacher 的此演讲 。他是 Jinja2 的作者,在本次演讲中他解释了如何在 Jinja2 中操作堆栈跟踪。如果我没记错的话,他正在使用 ctypes 来操作 Python C 级别的数据结构。顺便说一下,我认为这次演讲是整个 Europython 2011 最好的演讲。
You should have a look at this talk by Armin Ronacher. He's the author of Jinja2 and in this talk he explained, how he manipulates stack traces in Jinja2. If I remember correctly, he's using ctypes, to manipulate the data structures on the C level of Python. The talk was in my opinion the best talk of the whole Europython 2011 by the way.