You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何Python允许访问__all__未指定的模块元素?我的配置为何失效

关于Python模块from ... import *导出范围的疑问

目录结构

.
├── main.py
└── myproj
    ├── __init__.py
    └── mymodule.py

各文件内容

mymodule.py

hello = "hello"
byebye = "byebye"
class sayHello():
    def __init__(self):
        print("Hello World!")

class sayBye():
    def __init__(self):
        print("ByeBye World!")

myproj/init.py

为了实现from myproj import *时仅暴露sayHello类,我在__init__.py中添加了__all__:

__all__ = ["sayHello"]

问题现象

当执行from myproj.mymodule import *时,仍然能访问mymodule.py中的所有内容。比如main.py代码如下:

from myproj.mymodule import *

sayBye()
print(locals())

执行结果:

$ python main.py   
ByeBye World!
{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x10daf5210>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': '/Users/simon/junk/main.py', '__cached__': None, 'hello': 'hello', 'byebye': 'byebye', 'sayHello': <class 'myproj.mymodule.sayHello'>, 'sayBye': <class 'myproj.mymodule.sayBye'>}

原本预期执行sayBye()会报错,因为文档说明__all__指定的符号才会被导出,但实际不仅能调用sayBye,还能访问hello、byebye等变量。

原因分析

__all__的作用范围是当前模块/包:

  • 你在myproj/__init__.py中定义的__all__,只对from myproj import *生效,控制的是从包myproj导出的内容。
  • 而from myproj.mymodule import *是直接导入子模块mymodule的内容,此时生效的是mymodule.py自身定义的__all__(如果有的话),和包的__init__.py无关。

解决方案

如果要控制from myproj.mymodule import *的导出范围,需要在mymodule.py中添加自己的__all__:

__all__ = ["sayHello"]

hello = "hello"
byebye = "byebye"
class sayHello():
    def __init__(self):
        print("Hello World!")

class sayBye():
    def __init__(self):
        print("ByeBye World!")

修改后再执行main.py,就会触发NameError: name 'sayBye' is not defined,符合预期——此时from myproj.mymodule import *只会导入sayHello,其他变量/类无法直接访问。

内容的提问来源于stack exchange,提问作者Simon Ernesto Cardenas Zarate

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 19:40:57