К сожалению, это невозможно с inspect
, и вряд ли будет работать без повторного анализа (и компиляции) исходного кода.inspect
s getsource
метод довольно ограничен: он использует getsourcelines
для вызова затем findsource
, что по существу разворачивает ваш объект до тех пор, пока мыв итоге получим PyCodeObject
.
На этом этапе мы имеем дело с скомпилированным байт-кодом.Все, что осталось от исходного источника , это фрагменты и подсказки, такие как , например co_firstlineno
:
/* Bytecode object */
typedef struct {
/* ... other fields omitted ... */
int co_firstlineno; /* first source line number */
PyObject *co_code; /* instruction opcodes */
/* ... other fields omitted ... */
} PyCodeObject;
Кстати, аналогично PyCodeObject
,PyFrameObject
также содержит только столбец f_lineno
, но no , который объясняет, почему в трассировках указываются только имя файла и строка: столбец не компилируется вбайт-код.
Поскольку байт-код не содержит более конкретных областей, чем (первая) строка, невозможно получить точное местоположение источника из inspect
или любой другой библиотеки, которая использует только (общедоступную)информация байт-кода без дальнейшего анализа.Это также справедливо для любой другой опции, которая использует только байт-код, такой как pickle
.
inspect
использует общедоступную информацию (co_firstlineno
) и , а затем просто ищет подходящее началофункция и конец окружающего блока .Тем не менее, inspect
это почти там, но он находит только любой блок, а не правильный , и он не может найтиправильный на данный момент.inspect
токенизирует полную строку и не начинается с правильного варианта, он также не будет знать правильную соответствующую область исходного кода.
Скажем, у нас есть
plus, minus, mult = lambda x: x + 1, lambda y: y - 1, lambda z: z * 5
и мыхочу просто minus
.Поскольку байт-код не содержит co_firstcolumn
, у нас есть только полная доступная строка.Мы могли бы разобрать все лямбды, но мы до сих пор не знаем, какая лямбда подходит нашему co_code
.Нам нужно было бы скомпилировать их снова и проверить, соответствует ли их байт-код оригинальному.
В конце мы должны сделать именно это: снова проанализировать источник и найти правильный PyCodeObject
.Было бы намного проще, если бы у нас был хотя бы начальный номер столбца, поскольку мы могли бы просто использовать синтаксический анализ, но AST сохраняет только номеров строк на данный момент .Так что либо inspect
нужен большой патч, либо байт-код должен включать начальный столбец скомпилированного объекта.