这是script_one.py
:
x = "Hello World"
这是script_two.py
:
from script_one import x
print(x)
现在,如果我运行script_two.py
,输出将为:
>>> Hello World
我需要的是一种检测是否导入x
的方法
这就是我想象的script_one.py
的源代码:
x = "Hello World"
if x.has_been_imported:
print("You've just imported \"x\"!")
然后,如果我运行script_two.py
输出"应该" :
>>> Hello World
>>> You've just imported "x"!
这叫做什么,Python 3中是否存在此功能以及如何使用它?
答案 0 :(得分:2)
你不能。我试图发现这是浪费时间的努力,我很害怕。
Python导入包含以下步骤:
sys.modules
,检查模块是否已加载。
sys.modules
的新模块对象,其中包含执行顶级代码所产生的所有对象。import
变体。
import module
将名称module
绑定到sys.modules[module]
对象import module as othername
将名称othername
绑定到sys.modules[module]
对象from module import attribute
将名称attribute
绑定到sys.modules[module].attribute
对象from module import attribute as othername
将名称othername
绑定到sys.modules[module].attribute
对象在这种情况下,重要的是要认识到Python名称只是引用;所有Python对象(包括模块)都存在于堆中,并且随着对它们的引用数量的增加而停滞不前。如果您需要有关其工作原理的入门知识,请参阅此great article by Ned Batchelder on Python names。
您的问题可以通过两种方式解释:
x = "Hello World"
),它已被导入。所有的。 Python不会在这里加载 x
,它全部或全部。gc.get_referrers()
object chain以查看其他Python对象现在可能引用的x
。在以下任何一种情况下,后一目标变得越来越难:
import script_one
,然后使用script_one.x
;像这样的引用可能太短暂,你无法检测到。from script_one import x
,然后del x
。除非其他东西仍引用导入的命名空间中的相同字符串对象,否则该引用现在已经消失,无法再被检测到。import sys; sys.modules['script_one'].x
是引用相同字符串对象的合法方式,但这是否算作导入?import script_one
,然后list(vars(script_one).values())
将创建模块中定义的所有对象的列表,但这些引用是列表中的索引,而不是命名。这是否算作进口?答案 1 :(得分:0)
以前好像是不可能的。但是自从 python 3.7+ 在模块级别引入 __getattr__
以来,现在看起来是可能的。至少我们可以区分一个变量是通过from module import varable
还是import module; module.variable
导入的。
思路是检测上一帧的AST节点,是否是Attribute
:
script_one.py
def _variables():
# we have to define the variables
# so that it dosen't bypass __getattr__
return {'x': 'Hello world!'}
def __getattr__(name):
try:
out = _variables()[name]
except KeyError as kerr:
raise ImportError(kerr)
import ast, sys
from executing import Source
frame = sys._getframe(1)
node = Source.executing(frame).node
if node is None:
print('`x` is imported')
else:
print('`x` is accessed via `script_one.x`')
return out
script_two.py
from script_one import x
print(x)
# `x` is imported
# 'Hello world!'
import script_one
print(script_one.x)
# `x` is accessed via `script_one.x`
# 'Hello world!'