Mungkin terlambat untuk menjawab, tetapi saya tidak menemukan jawaban yang benar untuk diri saya sendiri. Solusi paling dekat dan tepat (lebih cepat dari inspect.stack()) di 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
Kelebihan :
- Lebih berharga daripada
globals()metode.
- Tidak bergantung pada bingkai perantara tumpukan, yang dapat ditambahkan misalnya, melalui pengait atau oleh alat 3dparty seperti
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
- Dapat menangani sesi pipa python atau interaktif.
Kekurangan:
- Semacam yang lebih tepat dan dapat mengembalikan modul yang terdaftar dalam bentuk yang dapat dieksekusi seperti
pytest.exeyang mungkin bukan yang Anda inginkan.
inspect.getmodule masih dapat mengembalikan None pada modul yang valid tergantung pada hooking
Saya memiliki ekstensi ke python:
Bagaimana cara mengimpor modul yang diberikan jalur lengkap?
Ekstensi yang memiliki fungsi pembungkus untuk kasus tersebut:
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>'):
...
Anda harus menginisialisasi ekstensi dengan benar:
# 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 ...