多个 if name == "__main__" 不能共存,python 只执行最后一个;正确做法是统一入口、封装函数并用 argparse 或环境变量分发,或通过 setuptools entry_points 管理多命令。

多个 if __name__ == "__main__" 怎么共存
不能共存,Python 解释器只认最后一个。常见错误是复制粘贴不同脚本时各自保留了 if __name__ == "__main__" 块,结果只有末尾那个生效,前面的逻辑彻底静默。
正确做法是统一入口:把所有主逻辑封装成函数,比如 main_cli()、main_worker()、main_dev(),然后在单个 if __name__ == "__main__" 里用 sys.argv 或 argparse 分发:
if __name__ == "__main__":
import sys
if len(sys.argv) > 1 and sys.argv[1] == "worker":
main_worker()
elif len(sys.argv) > 1 and sys.argv[1] == "dev":
main_dev()
else:
main_cli()
- 别用
os.system("python script2.py")启动另一个入口——进程隔离、参数传递麻烦、异常难捕获 -
argparse比手动查sys.argv更健壮,尤其要支持--help和子命令时 - 如果入口差异大(比如一个跑 HTTP 服务,一个跑定时任务),建议拆成独立脚本文件,而非硬塞进一个文件
用 setuptools 配 entry_points 管多个命令
这是发布级组织方式,适合打包后通过命令行直接调用,比如 mytool cli、mytool sync。核心是 setup.py 或 pyproject.toml 里声明 entry_points。
在 pyproject.toml 中写:
立即学习“Python免费学习笔记(深入)”;
[project.entry-points."console_scripts"] mytool-cli = "mytool.cli:main" mytool-sync = "mytool.sync:main" mytool-clean = "mytool.utils:clean_cache"
- 每个值格式必须是
"模块路径:可调用对象名",中间冒号不能漏,也不能多空格 - 模块路径从包根开始算,不是相对路径;确保该模块能被 Python 正常 import(即有
__init__.py或符合 PEP 420) -
pip install -e .后命令才可用;不加-e就得先pip install .再测试 - Windows 上偶尔因 shebang 或路径缓存导致新命令不生效,可删掉
%USERPROFILE%\AppData\Roaming\pip\pip.ini或重启终端
同一个脚本里混用 click 和原生 argparse
别混。两者都试图接管 sys.argv 解析和帮助输出,叠加会导致参数错乱、--help 重复打印、子命令注册失败等现象,错误信息往往不明确,比如 unrecognized arguments: --help 却又没提示可用选项。
eSiteGroup站群管理系统是基于eFramework低代码开发平台构建,是一款高度灵活、可扩展的智能化站群管理解决方案,全面支持SQL Server、SQLite、MySQL、Oracle等主流数据库,适配企业级高并发、轻量级本地化、云端分布式等多种部署场景。通过可视化建模与模块化设计,系统可实现多站点的快速搭建、跨平台协同管理及数据智能分析,满足政府、企业、教育机构等组织对多站点统一管控的
选一个到底:
- 简单场景(1–2 个开关参数)用原生
argparse,零依赖,启动快 - 需要子命令、选项分组、类型自动转换、颜色帮助页,就用
click;它对多入口更友好,@click.group()天然支持mytool db migrate这种嵌套调用 - 如果已有
argparse脚本想升级为多命令,不要强行套click,而是把各子命令逻辑抽成函数,再用click.group()包一层,而不是保留旧的ArgumentParser实例
调试时怎么快速切换不同入口而不改代码
靠环境变量或临时配置最稳。硬编码判断 sys.argv 在 IDE 里调试不方便,每次都要改运行参数;而环境变量可以全局设置一次,所有入口都读取。
例如在脚本开头加:
import os
ENTRY_POINT = os.getenv("MYTOOL_ENTRY", "cli")
然后在 if __name__ == "__main__" 里根据 ENTRY_POINT 分发。调试时只需在 IDE 的 Run Configuration 里设环境变量,或终端里:
MYTOOL_ENTRY=worker python mytool/__main__.py
- 避免用文件存在与否判断入口(如
if os.path.exists("dev.flag")),容易误提交、权限出问题、CI 环境不一致 - 别用
__file__名称匹配来区分入口,重命名脚本就失效,且无法支持entry_points安装后的调用 - 如果入口间共享大量初始化逻辑(如日志配置、DB 连接),把这些提前抽到单独函数,所有入口都先调用它,而不是复制粘贴
多入口真正的复杂点不在写法,而在状态隔离——比如一个入口开了全局线程池,另一个入口又去关它,或者两个入口同时读写同一份缓存文件。这种问题不会报错,但会悄悄破坏行为一致性。









