检查谁进口了我

wim*_*wim 5 python introspection python-import python-3.x

有两个文件:

# 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))
Run Code Online (Sandbox Code Playgroud)

和:

# the_importer.py
import the_imported
Run Code Online (Sandbox Code Playgroud)

使用 Python 2.7 执行时:

$ python the_importer.py 
the_imported was imported by the_importer.py
Run Code Online (Sandbox Code Playgroud)

使用 Python 3.5 执行时:

$ python3 the_importer.py 
the_imported was imported by <frozen importlib._bootstrap>
Run Code Online (Sandbox Code Playgroud)

这到底是怎么回事<frozen importlib._bootstrap>?发生了什么import和/或inspect改变了这种行为?我们怎样才能让 Python 2 文件名自省在 Python 3 上再次运行?

Mar*_*nen 6

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

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

输出:

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
Run Code Online (Sandbox Code Playgroud)

你可以这样做:

# 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)
Run Code Online (Sandbox Code Playgroud)

输出:

C:\Users\user\Desktop\the_importer.py
Run Code Online (Sandbox Code Playgroud)


vau*_*tah 4

在 Python 3.1 及更高版本中,导入机制是用 Python 实现的,这使得可以访问其调用堆栈。为了说明这一点,我将输入以下代码

from traceback import print_stack
print_stack()
Run Code Online (Sandbox Code Playgroud)

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()
Run Code Online (Sandbox Code Playgroud)

但在 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()
Run Code Online (Sandbox Code Playgroud)

在 Python 3.3 之前,这些行也包含在 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
Run Code Online (Sandbox Code Playgroud)