2016-12-03 24 views
2

有两个文件:检查谁进口我

# 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和/或inspect发生了什么改变了这种行为?我们如何才能在Python 3上再次使用Python 2文件名自省功能?

回答

2

在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 
3

只是有更多的堆栈在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 

输出:

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