如何检测类/变量是否已在 Python 3 中导入?

3 python import python-import python-3.x

这是以下内容script_one.py

x = "Hello World"
Run Code Online (Sandbox Code Playgroud)

这是以下内容script_two.py

from script_one import x
print(x)
Run Code Online (Sandbox Code Playgroud)

现在,如果我运行,script_two.py输出将是:

>>> Hello World
Run Code Online (Sandbox Code Playgroud)

我需要的是一种检测是否x已导入的方法。
这就是我想象的源代码的样子script_one.py

x = "Hello World"
if x.has_been_imported:
  print("You've just imported \"x\"!")
Run Code Online (Sandbox Code Playgroud)

然后,如果我运行script_two.py输出“应该”是:

>>> Hello World
>>> You've just imported "x"!
Run Code Online (Sandbox Code Playgroud)

这叫什么,Python 3 中是否存在此功能以及如何使用它?

Mar*_*ers 5

你不能。恐怕花费在尝试检测这一点上的努力是浪费时间。

Python 导入包含以下步骤:

  • 通过查看 来检查模块是否已加载sys.modules
    • 如果模块尚未加载,请加载它。这将创建一个添加到 的新模块对象sys.modules,其中包含执行顶级代码所产生的所有对象。
  • 在导入命名空间中绑定名称。名称的绑定方式取决于import所选的具体变体。
    • import module将名称绑定modulesys.modules[module]对象
    • import module as othername将名称绑定othernamesys.modules[module]对象
    • from module import attribute将名称绑定attributesys.modules[module].attribute对象
    • from module import attribute as othername将名称绑定othernamesys.modules[module].attribute对象

在这种情况下,重要的是要认识到 Python 名称只是引用;所有Python对象(包括模块)都存在于堆中,并根据对它们的引用数量而变化。如果您需要了解Python 名称的工作原理,请参阅 Ned Batchelder 撰写的这篇精彩文章。

那么你的问题可以用两种方式解释:

  • 您想知道模块已导入。当模块中的代码被执行时(如x = "Hello World"),它就被导入了。所有的。Python 不只 x这里加载,要么全部加载,要么全无加载。
  • 您想知道其他代码是否正在使用特定名称。您必须跟踪该对象存在哪些其他引用。这是一项艰巨的任务,涉及递归检查gc.get_referrers()对象链以查看其他 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())将创建模块中定义的所有对象的列表,但这些引用是列表中的索引,而不是命名。这算不算进口?