python服务中修改的.py文件未生效,主因是模块已加载进内存且.pyc缓存优先、路径指向错误(如site-packages而非本地)、进程未真正重启、或代码被冻结在zip/打包环境中;需检查__file__与__loader__、清除__pycache__、强制终止进程并验证字节码来源。

修改的.py文件根本没被加载
Python服务启动时不会自动重载已导入的模块,哪怕你改了源码、重启了进程,只要模块已在内存中,就继续用旧字节码。常见于用import一次性导入后长期驻留的后台服务(如Flask/Gunicorn、Celery worker、自定义daemon)。
排查方法:在服务代码里加一行print(__file__)或print(inspect.getfile(your_module)),确认实际加载路径是否指向你修改的那个文件——很多人改的是site-packages里的副本,但服务加载的是venv里另一个同名包,或者反之。
- 用
pip show package_name查安装路径,再对比your_module.__file__ - 检查是否用了
python -m package方式启动,此时可能绕过当前目录,优先加载已安装版本 - 确认没在多个位置同时安装同一包(比如
pip install -e .和pip install .共存)
pyc缓存未清除或覆盖了修改
Python会把编译后的.pyc文件存在__pycache__目录或__pycache__/子目录下,且默认按Python版本+时间戳命名。即使你改了.py,只要.pyc时间戳更新晚于.py,解释器仍会直接加载它。
尤其在容器或打包环境里,构建时生成的.pyc可能被固化进镜像,运行时完全忽略源码变更。
- 手动删掉所有
__pycache__目录和.pyc文件:find . -name "__pycache__" -type d -exec rm -rf {} +;find . -name "*.pyc" -delete - 启动时加
-B参数禁止生成.pyc:python -B your_service.py - Docker中在
ENTRYPOINT前加find /app -name "*.pyc" -delete
服务进程没真正重启
很多“重启”只是发了个SIGHUP或调了reload接口,对多进程/守护进程模型无效。比如Gunicorn的kill -s HUP $PID只重载worker进程,但主进程仍持旧模块引用;Supervisor的supervisorctl restart若配置了autostart=false,可能根本没拉起新实例。
更隐蔽的是:某些框架(如FastAPI + Uvicorn)在开发模式下才启用热重载,生产模式默认关闭,--reload不生效也不报错。
- 用
ps aux | grep python确认旧进程PID是否彻底消失 - 检查服务日志里是否有“starting”、“booting”等初始化字样,而不是“reloading”
- 强制终止再启动:
pkill -f "your_service.py"后再手动运行 - Uvicorn生产部署必须显式加
--reload,且仅限开发环境;生产请用systemd或supervisord完整启停
包被冻结或以zipimport方式加载
有些打包工具(PyInstaller、cx_Freeze)或PaaS平台(如AWS Lambda层)会把整个包打成.zip或嵌入到可执行体中。此时修改磁盘上的.py文件完全无效——解释器从zip archive或内存映射段读取代码。
典型现象:your_module.__file__返回类似/tmp/_MEIXXXXXX/your_package/xxx.py或zipimporter object。
- 检查
your_module.__loader__类型,如果是zipimport.ZipImporter,说明走的是压缩包路径 - PyInstaller打包后,必须重新运行
pyinstaller命令生成新exe,不能只改源码 - Lambda函数更新代码必须重新部署.zip包,不能SSH进去改
__file__和__loader__指向你预期的位置,再清缓存、杀进程、验证输出。Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











