Предположим, myapp/foo.py
содержит:
def info(msg):
caller_name = ????
print '[%s] %s' % (caller_name, msg)
И myapp/bar.py
содержит:
import foo
foo.info('Hello') # => [myapp.bar] Hello
В этом случае я хочу caller_name
установить __name__
атрибут модуля вызывающих функций (которым является myapp.foo). Как это может быть сделано?
python
stack-trace
introspection
Шридхар Ратнакумар
источник
источник
caller_name
не может быть__main__
Ответы:
Проверьте модуль проверки:
inspect.stack()
вернет информацию о стеке.Внутри функции
inspect.stack()[1]
вернет стек вашего вызывающего. Оттуда вы можете получить дополнительную информацию об имени вызывающей функции, модуле и т. Д.Подробнее см. В документации:
http://docs.python.org/library/inspect.html
Кроме того, Дуг Хеллманн написал хорошую статью о модуле inspect в своей серии PyMOTW:
http://pymotw.com/2/inspect/index.html#module-inspect
РЕДАКТИРОВАТЬ: Вот какой-то код, который делает то, что вы хотите, я думаю:
import inspect def info(msg): frm = inspect.stack()[1] mod = inspect.getmodule(frm[0]) print '[%s] %s' % (mod.__name__, msg)
источник
__name__
атрибут этого модуля с помощьюinspect
модуля? Например, как мне вернутьсяmyapp.foo
(неmyapp/foo.py
) в мой пример выше? Я уже пробовал использовать модуль проверки перед публикацией в SO.inspect.stack()[2]
для реального вызывающего абонента.Столкнувшись с аналогичной проблемой, я обнаружил, что sys._current_frames () из модуля sys содержит интересную информацию, которая может помочь вам без необходимости импорта inspect, по крайней мере, в определенных случаях использования.
>>> sys._current_frames() {4052: <frame object at 0x03200C98>}
Затем вы можете "подняться" с помощью f_back:
>>> f = sys._current_frames().values()[0] >>> # for python3: f = list(sys._current_frames().values())[0] >>> print f.f_back.f_globals['__file__'] '/base/data/home/apps/apricot/1.6456165165151/caller.py' >>> print f.f_back.f_globals['__name__'] '__main__'
В качестве имени файла вы также можете использовать f.f_back.f_code.co_filename, как было предложено Марком Родди выше. Я не уверен в ограничениях и предостережениях этого метода (скорее всего, проблема с несколькими потоками), но я намерен использовать его в своем случае.
источник
sys._getframe(1)
вместо вызоваsys._current_frames()
(кстати, который возвращает отображение кадра для каждого потока).inspect.currentframe()
вместоsys._current_frames().values()[0]
.Я не рекомендую этого делать, но вы можете достичь своей цели следующим методом:
def caller_name(): frame=inspect.currentframe() frame=frame.f_back.f_back code=frame.f_code return code.co_filename
Затем обновите существующий метод следующим образом:
def info(msg): caller = caller_name() print '[%s] %s' % (caller, msg)
источник
__name__