Так что я смог частично понять это, покопавшись в исходном коде IPython.Он использует встроенный модуль linecache , который содержит функции для чтения исходного кода из файлов и кэширования результатов.Оба модуля inspect
и traceback
используют этот модуль для получения источника функции.
Решение состоит в том, чтобы создать функцию так же, как в вопросе, но с использованием compile
с-up и уникальное имя файла:
source = 'def foo(x, y):' + '\n\t' + 'return x / y'
filename = '<dynamic-123456>' # Angle brackets may be required?
code = compile(source, filename, 'exec')
g = {numpy: numpy, ...} # Modules and such required for function
l = {}
exec(src, g, l)
func = l['foo']
linecache
содержит переменную cache
, которая представляет собой словарь, сопоставляющий имена файлов с (size, mtime, lines, fullname)
кортежами.Вы можете просто добавить запись для поддельного имени файла:
lines = [line + '\n' for line in source.splitlines()]
import linecache
linecache.cache[filename] = (len(source), None, lines, filename)
Затем функция будет работать с inspect.getsource()
, синтаксисом IPython ?
/ ??
и трассировками IPython.Тем не менее, он все еще не работает во встроенных трассировках.Это в основном достаточно для меня, потому что я почти всегда работаю в IPython.
РЕДАКТИРОВАТЬ: см. Комментарий user2357112 ниже о том, как заставить это работать с печатью трассировки во встроенном интерпретаторе.