【问题标题】:Why can Python not see previously imported modules?为什么 Python 看不到以前导入的模块?
【发布时间】:2021-05-22 15:41:19
【问题描述】:

假设有两个文件a.py 和b.py。里面有以下内容:

# a.py
from b import foo

foo()

# b.py
import os

def foo():
    print(os.cwd())

这很好用,但为什么a.py 无法隐式看到b.py 的导入供自己使用:

# a.py
import b

def bar():
    print(os.cpu_count())  # fails

b.foo()
bar()

# b.py
import os

def foo():
    print(os.cwd())

我正在阅读 import system 文档,但无法弄清楚这一点。 os 导入存在于 b.py 的命名空间中,但它对 a.py 不可用,我不确定为什么。 globals() 方法是在模块级别,所以给定rules,模块之间是否没有共享导入(不使用__all__ 和* 导入)?每个模块都有自己的导入命名空间吗?

【问题讨论】:

  • os 仅在 b 内部导入。这意味着os 是该文件的本地文件。但是,因为您已经导入了b,所以您可以使用b.os 访问os。除非您发出星型导入,例如:from b import *,否则它们将拥有自己的命名空间。
  • 每个模块都有自己的命名空间句号。 import 做了两件事:如果模块尚不存在,则将其拉入导入缓存中, 并 将引用(指向该缓存)添加到当前模块的 __globals__(即当前模块的命名空间)。
  • @HampusLarsson, ...sure, from os import * 表示您没有从当前模块的命名空间中添加对 os 的引用(而是添加对 os.__all__ 中每个元素的单独引用),但这并不意味着模块仍然有自己的命名空间,这就是我解释你最后一句话的方式。

标签: python python-internals


【解决方案1】:

每个模块都有自己的命名空间。 import 语句做了两件事:如果一个模块在当前进程中还没有被导入,它就会被加载并执行。之后,它的名称将绑定到 import 语句所在的本地命名空间。

如果一个模块已经在同一个进程中被导入,它不会被重新加载,但是导入语句中的名称被导入语句正确绑定。

正确的做法是在您的 a 模块上添加另一个 import os - 但如果你这样做import b,你可以使用b.os.cwd()(因为“os”是模块b执行后的绑定名称)

【讨论】:

  • 而事实上,os 是通常由解释器在启动时创建的模块之一,因此import os 实际上总是只在本地命名空间中创建一个新名称通过sys.modules['os']绑定到模块accessbile。
猜你喜欢
  • 2017-10-11
  • 2012-03-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-01-25
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多