检查谁进口了我

inspect who imported me

有两个文件:

# the_imported.py
import inspect
imported_by_fname = inspect.currentframe().f_back.f_code.co_filename
print('{} was imported by {}'.format(__name__, imported_by_fname))

并且:

# the_importer.py
import the_imported

用Python执行时 2.7:

$ python the_importer.py 
the_imported was imported by the_importer.py

用Python执行时 3.5:

$ python3 the_importer.py 
the_imported was imported by <frozen importlib._bootstrap>

那个奇怪的东西 <frozen importlib._bootstrap> 到底是怎么回事? import and/or inspect 发生了什么改变了这种行为?我们怎样才能让 Python 2 文件名内省再次在 Python 3 上工作?

Python3 中的堆栈中还有更多内容。importlib 现在负责导入:

# the_imported.py
from inspect import getframeinfo, getouterframes, currentframe
frame = currentframe()
while frame:
    print(frame.f_code.co_filename)
    frame = frame.f_back

输出:

C:\Users\user\Desktop\the_imported.py
<frozen importlib._bootstrap>
<frozen importlib._bootstrap>
<frozen importlib._bootstrap>
<frozen importlib._bootstrap>
<frozen importlib._bootstrap>
<frozen importlib._bootstrap>
<frozen importlib._bootstrap>
<frozen importlib._bootstrap>
C:\Users\user\Desktop\the_importer.py

你可以这样做:

# the_imported.py
from inspect import getframeinfo, getouterframes, currentframe
frame = currentframe().f_back
while frame.f_code.co_filename.startswith('<frozen'):
    frame = frame.f_back
print(frame.f_code.co_filename)

输出:

C:\Users\user\Desktop\the_importer.py

在 Python 3.1 和更新版本中,import machinery 在 Python 中实现,这使得访问其调用堆栈成为可能。为了说明这一点,我将放置以下代码

from traceback import print_stack
print_stack()

the_imported.py并导入。

在 Python 2 代码打印

  File "the_importer.py", line 2, in <module>
    import the_imported
  File ".../the_imported.py", line 3, in <module>
    print_stack()

但是在 Python 3 上输出更加冗长:

  File "the_importer.py", line 2, in <module>
    import the_imported
  File "<frozen importlib._bootstrap>", line 961, in _find_and_load
  File "<frozen importlib._bootstrap>", line 950, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 655, in _load_unlocked
  File "<frozen importlib._bootstrap_external>", line 677, in exec_module
  File "<frozen importlib._bootstrap>", line 205, in _call_with_frames_removed
  File ".../the_imported.py", line 2, in <module>
    print_stack()

在 Python 3.3 之前,这些行 were also included in tracebacks.

要获得所需的结果,您可以在调用堆栈中向上查找第一帧,其文件名不以 <frozen importlib.

开头
from traceback import extract_stack

for x in extract_stack():
    if not x[0].startswith('<frozen importlib'):
        print('{} was imported by {}'.format(__name__, x[0]))
        break