How to rewrite a specific frame in a traceback?

一笑奈何 提交于 2019-12-21 22:14:12

问题


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.


回答1:


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.




回答2:


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.




回答3:


How about something like this:

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


来源:https://stackoverflow.com/questions/8181532/how-to-rewrite-a-specific-frame-in-a-traceback

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!