Python源码文件必须用.py扩展名是因工具链生态共识而非语法强制,import、IDE、pip等均依赖该后缀识别和处理文件。

为什么 Python 源码文件必须用 .py 扩展名
Python 解释器本身不强制要求扩展名,但几乎所有工具链(python 命令、IDE、包管理器、import 机制)都默认只识别 .py。这不是语法限制,而是约定驱动的生态共识。
常见错误现象:python myscript 报错 ModuleNotFoundError 或直接提示“no such file”,其实是因为你写了 myscript 而不是 myscript.py;又或者 import utils 失败,只因实际文件叫 utils.txt。
-
import语句只查找.py文件(以及已编译的.pyc,但前提是对应.py存在) - VS Code / PyCharm 等编辑器依赖
.py后缀启用语法高亮、补全和调试支持 -
pip install -e .构建时,setup.py或pyproject.toml中的packages发现逻辑也基于.py文件扫描
.pyc 文件不是缓存,是字节码——且不能手动运行
.pyc 是 Python 编译后的字节码文件,存在 __pycache__ 目录下,名字含 Python 版本标识(如 main.cpython-311.pyc)。它不等价于“编译产物可执行文件”,也不能脱离解释器独立运行。
使用场景:模块首次导入时生成,后续导入若 .py 未修改,则直接加载 .pyc 加速启动——但这个过程完全由解释器控制,用户无需、也不该干预。
立即学习“Python免费学习笔记(深入)”;
- 删掉
.pyc不影响功能,下次导入会自动重建 - 把
.pyc复制到另一台机器运行?大概率失败——因为字节码版本与 Python 解释器版本强绑定(cpython-39的.pyc在 3.11 下无法加载) -
python script.pyc会报错ImportError: bad magic number,必须用python -m py_compile或通过import触发加载
其他扩展名如 .pyw、.pyi 是特定用途,别乱用
.pyw 只在 Windows 生效,双击运行时不弹命令行窗口,专用于 GUI 程序(如用 tkinter 或 PyQt 写的工具)。它和 .py 内容完全兼容,只是启动方式不同。
.pyi 是类型存根文件(stub),供 mypy 或 IDE 做静态类型检查用,本身不可执行,也不参与运行时。
- Linux/macOS 下
.pyw和.py行为一致,无特殊处理 -
.pyi文件必须和对应.py同名,放在同一目录或typings/下,否则类型检查工具找不到 - 不要把脚本改成
.pyi试图“隐藏逻辑”——它只是注释性文件,不包含可执行代码
部署时要不要保留 .py?看场景,但别删了再后悔
生产环境打包(如用 pyinstaller 或 docker)常有人想“只留 .pyc 省空间”或“删掉源码防泄露”。这想法危险且低效。
性能影响几乎为零:一个 .py 文件几 KB,而 .pyc 大小相近,且解释器加载时仍需校验源码时间戳或哈希(CPython 3.7+ 使用 importlib.util.cache_from_source() 生成路径,但校验逻辑仍在)。
- 删掉
.py后,traceback里显示的全是<string></string>或空行,调试等于抓瞎 -
pyinstaller --onefile本身会把.py编译进归档,不需要你手动留.pyc - 想防源码?加密或混淆更靠谱,删
.py只会让运维和协作成本飙升
真正容易被忽略的是:.py 文件权限、换行符(\r\n 在 Linux 上可能让 #!/usr/bin/env python 失效)、BOM 头(Windows 记事本保存的 UTF-8-BOM 会导致 SyntaxError: Non-UTF-8 code starting with '\xff')——这些比纠结扩展名更常引发线上故障。



















