Как переписать конкретный кадр в трассировке? - PullRequest
2 голосов
/ 18 ноября 2011

В python вы можете скомпилировать () строку, которая будет выполняться быстрее с exec (). Но как только я его использую, мы теряем информацию, когда в 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, и они тоже переписывают traceback, но не для содержимого. Нужен ли мне кастом, кроме крючка? Я обеспокоен тем, что, поскольку он не находится в самой трассировке, если пользователь / модуль / что-либо еще делает исключение, трассировка не будет содержать ценной информации.

Ответы [ 3 ]

3 голосов
/ 26 ноября 2011

Вы должны взглянуть на этот разговор Армина Ронахера.Он является автором Jinja2 и в этом выступлении он объяснил, как он манипулирует следами стека в Jinja2.Если я правильно помню, он использует ctypes, чтобы манипулировать структурами данных на уровне C Python.Между прочим, эта беседа, на мой взгляд, была лучшей из всех Europython 2011 года.

2 голосов
/ 08 февраля 2012

После глубокого поиска это невозможно, CPython использует свой собственный API, чтобы определить, где находится файл и т. Д., И он не может быть исправлен в чистом Python.

0 голосов
/ 18 ноября 2011

Как насчет этого:

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