from module import * 会将模块中所有公有名称直接导入当前命名空间,导致命名冲突、污染作用域、降低可读性与可维护性,应严格避免在生产代码中使用。

from module import * 会直接污染当前命名空间
它不是“导入模块”,而是把 module 里所有未以下划线开头的名称(即默认公有名称),一股脑复制进当前作用域。这些名称和你本地已有的变量、函数、类完全平级,没有任何前缀或隔离。一旦发生重名,后导入的会静默覆盖前面的——连警告都没有。
常见错误现象:
-
from json import *后再定义def dumps(): ...,你的dumps就被标准库的dumps覆盖了 - 两个不同模块都导出
load,from a import *再from b import *,后者必然胜出,但你根本看不出哪次导入生效 - 调试时
print(load)显示的是哪个load?得翻源码、查sys.modules,效率极低
它让代码可读性和可维护性断崖下跌
阅读代码时,看到一个裸名 query,你无法立刻判断它来自哪里:是本地定义?是 sqlalchemy 的?还是你自己写的 utils.py?IDE 的跳转、重命名、静态检查全部失效。
使用场景中尤其危险:
- 在
__init__.py里用from .submod import *,相当于把子模块接口全暴露到包顶层,后续新增同名函数极易破坏下游调用 - 团队协作时,A 同学加了个
parse(),B 同学同步加了另一个parse(),谁的会被最终导入?取决于导入顺序,而顺序常由文件系统遍历决定,不可控 - CI 流程中,不同 Python 版本对
__all__的处理略有差异,import *行为可能漂移
替代方案比 * 更明确、更安全
真正需要的从来不是“省几个字符”,而是“知道名字从哪来、会不会撞车”。
推荐做法:
- 用
import module+ 点号访问:requests.get()、pathlib.Path()—— 清晰、无冲突、易溯源 - 精确导入必需项:
from datetime import datetime, timedelta—— 只暴露你需要的,且一目了然 - 必要时用
as重命名:from html import escape as html_escape,from xml.sax.saxutils import escape as xml_escape - 模块作者应主动设
__all__,控制from module import *的输出范围,但这不等于鼓励别人用*
唯一勉强能用的场景:交互式环境临时探索
在 IPython 或 Jupyter 里快速试一个模块的 API,from numpy import * 确实省事。但只要代码要保存、要复用、要进版本库,就必须立刻改掉。
容易被忽略的一点:即使你没写 import *,某些第三方包的 __init__.py 里写了,比如早期的 scipy。这时你要检查它的 __all__,或直接绕过顶层,用 from scipy.linalg import svd 这种精确路径。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











