#python #bytecode #inspect
#python #байт-код #Осмотр
Вопрос:
Приведенная ниже функция работает просто отлично. Но если я удалю все py
файлы (и оставлю pyc
их нетронутыми), я получу сообщение об ошибке:
Чтобы объяснить, что я подразумеваю под «неповрежденным», вот более или менее то, что я сделал: 1. напишите кучу файлов py и поместите их в понятную структуру каталогов 2. протестируйте код кода. Это работает 3. скомпилируйте все файлы py, чтобы получить файлы pyc 4. удалите файлы py 5. протестируйте код. Сбой
Функция:
def get_module_name_and_line():
"""
return the name of the module from which the method calling this method was called.
"""
import inspect
lStack = inspect.stack()
oStk = lStack[2]
oMod = inspect.getmodule(oStk[0])
oInfo = inspect.getframeinfo(oStk[0])
sName = oMod.__name__ #<<<<<<<<<<<<<<<<<< ERROR HERE
iLine = oInfo.lineno
return sName,iLine
Ошибка:
AttributeError: 'NoneType' object has no attribute '__name__'
Так oMod
None
и в этой ошибке. Если файлы py находятся рядом, то oMod
никогда None
.
Вопрос:
Почему inspect возвращает модуль только в том случае, если файлы py не повреждены? Как я могу заставить эту функцию работать без файлов py.
Полная трассировка:
Original exception was:
Traceback (most recent call last):
File "/home/criticalid/programs/damn.py", line 630, in <module>
File "/home/criticalid/programs/golly/class_foo.py", line 121, in moo
File "/home/criticalid/programs/golly/class_foo.py", line 151, in get_module_name_and_line
AttributeError: 'NoneType' object has no attribute '__name__'
Комментарии:
1. Я не уверен, что вы подразумеваете под «файлами py нетронутыми». В этом коде, я думаю, вы могли бы попробовать
sname = oMod.__name if oMod else 'Unknown Name'
то же самое для iLINE. Таким образом, ваш метод, по крайней мере, вернет2. @RobertEkendahl: неповрежденный означает не удаленный. Если у меня есть файлы py, все работает. Если у меня есть только файлы pyc, то он ломается
3. @Sheena: верно, без
.py
исходных файлов трассировка намного … реже. Это дает понять, что ваше исключение не вgetmodule()
вызове, а только в том, что возвращаетсяNone
.4. @MartijnPieters: точно. Но я не знаю, почему он возвращается
None
. Функция вызывается точно так же, единственное отличие — отсутствие файлов py. Может ли быть так, что модулю inpect нужны файлы py для правильной работы? Я предположил, что удаление файлов py не будет иметь значения, потому что байт-код будет точно таким же в любом случае.5. Вы пробовали не удалять свой исходный код? .pyc-файлы представляют собой недокументированную деталь реализации.
Ответ №1:
Это работает для меня. Предполагается, что все модули находятся в пакетах в текущем рабочем каталоге. И он возвращает не __main__
модуль, а его имя файла.
Я уверен, что есть лучшее решение, но это решает мои проблемы.
def get_module_name_and_line():
"""
return the name of the module from which the method calling this method was called.
"""
def get_name_from_path(sPath):
import os
sCWD = os.getcwd()
lCWD = list(os.path.split(sCWD))
lPath = list(os.path.split(sPath))
lPath[-1] = '.'.join(lPath[-1].split('.')[:-1]) #remove file extension
lRet = [s for s in lPath[len(lCWD)-1:]]
return '.'.join(lRet)
import inspect
lStack = inspect.stack()
oStk = lStack[2]
iLine = inspect.getlineno(oStk[0])
sName = get_name_from_path(inspect.getfile(oStk[0]))
return sName,iLine