Puede que sea tarde para responder, pero no encontré la respuesta correcta para mí. La solución más cercana y precisa (más rápida que inspect.stack()) en Python 3.7.x:
# search for first module in the stack
stack_frame = inspect.currentframe()
while stack_frame:
print('***', stack_frame.f_code.co_name, stack_frame.f_code.co_filename, stack_frame.f_lineno)
if stack_frame.f_code.co_name == '<module>':
if stack_frame.f_code.co_filename != '<stdin>':
caller_module = inspect.getmodule(stack_frame)
else:
# piped or interactive import
caller_module = sys.modules['__main__']
if not caller_module is None:
#... do something here ...
break
stack_frame = stack_frame.f_back
Pros :
- Más preciso que el
globals()método.
- No depende de los marcos intermedios de la pila, que se pueden agregar, por ejemplo, mediante hooking o mediante las herramientas de 3dparty como
pytest:
*** foo ... ..
*** boo ... ..
*** runtest c:\python\x86\37\lib\site-packages\xonsh\pytest_plugin.py 58
*** pytest_runtest_call c:\python\x86\37\lib\site-packages\_pytest\runner.py 125
*** _multicall c:\python\x86\37\lib\site-packages\pluggy\callers.py 187
*** <lambda> c:\python\x86\37\lib\site-packages\pluggy\manager.py 86
*** _hookexec c:\python\x86\37\lib\site-packages\pluggy\manager.py 92
*** __call__ c:\python\x86\37\lib\site-packages\pluggy\hooks.py 286
*** <lambda> c:\python\x86\37\lib\site-packages\_pytest\runner.py 201
*** from_call c:\python\x86\37\lib\site-packages\_pytest\runner.py 229
*** call_runtest_hook c:\python\x86\37\lib\site-packages\_pytest\runner.py 201
*** call_and_report c:\python\x86\37\lib\site-packages\_pytest\runner.py 176
*** runtestprotocol c:\python\x86\37\lib\site-packages\_pytest\runner.py 95
*** pytest_runtest_protocol c:\python\x86\37\lib\site-packages\_pytest\runner.py 80
*** _multicall c:\python\x86\37\lib\site-packages\pluggy\callers.py 187
*** <lambda> c:\python\x86\37\lib\site-packages\pluggy\manager.py 86
*** _hookexec c:\python\x86\37\lib\site-packages\pluggy\manager.py 92
*** __call__ c:\python\x86\37\lib\site-packages\pluggy\hooks.py 286
*** pytest_runtestloop c:\python\x86\37\lib\site-packages\_pytest\main.py 258
*** _multicall c:\python\x86\37\lib\site-packages\pluggy\callers.py 187
*** <lambda> c:\python\x86\37\lib\site-packages\pluggy\manager.py 86
*** _hookexec c:\python\x86\37\lib\site-packages\pluggy\manager.py 92
*** __call__ c:\python\x86\37\lib\site-packages\pluggy\hooks.py 286
*** _main c:\python\x86\37\lib\site-packages\_pytest\main.py 237
*** wrap_session c:\python\x86\37\lib\site-packages\_pytest\main.py 193
*** pytest_cmdline_main c:\python\x86\37\lib\site-packages\_pytest\main.py 230
*** _multicall c:\python\x86\37\lib\site-packages\pluggy\callers.py 187
*** <lambda> c:\python\x86\37\lib\site-packages\pluggy\manager.py 86
*** _hookexec c:\python\x86\37\lib\site-packages\pluggy\manager.py 92
*** __call__ c:\python\x86\37\lib\site-packages\pluggy\hooks.py 286
*** main c:\python\x86\37\lib\site-packages\_pytest\config\__init__.py 90
*** <module> c:\Python\x86\37\Scripts\pytest.exe\__main__.py 7
- Puede manejar una sesión interactiva o canalizada en Python.
Contras:
- Una especie de módulos muy precisos y que pueden devolver registrados en un ejecutable como el
pytest.exeque podría no ser lo que quieres.
inspect.getmodule aún puede devolver None en módulos válidos dependiendo del enlace
Tengo una extensión para Python:
¿Cómo importar un módulo dada la ruta completa?
La extensión que tiene funciones de envoltura para ese caso:
def tkl_get_stack_frame_module_by_offset(skip_stack_frames = 0, use_last_frame_on_out_of_stack = False):
...
def tkl_get_stack_frame_module_by_name(name = '<module>'):
...
Solo tienes que inicializar la extensión correctamente:
# portable import to the global space
sys.path.append(<path-to-tacklelib-module-directory>)
import tacklelib as tkl
tkl.tkl_init(tkl, global_config = {'log_import_module':os.environ.get('TACKLELIB_LOG_IMPORT_MODULE')})
# cleanup
del tkl # must be instead of `tkl = None`, otherwise the variable would be still persist
sys.path.pop()
# use `tkl_*` functions directly from here ...