当Python遇到“真假美猴王”:__main__ 与 __mp_main__ 的恩怨情仇

01 深夜的报错,像极了爱情

凌晨 2:30,我正用 NiceGUI 撸一个颜值报表,代码写完,帅气地一按回车——

You must call ui.run() to start the server.

???
我明明写了 ui.run() 啊!难道 Python 也熬夜熬到失忆?


02 真入口 vs 假入口:导演,他加戏!

原来,在 Windows 的舞台上,Python 的 multiprocessing 喜欢搞“替身文学”

场景 __name__ 身份
你双击脚本 "__main__" 真·入口
multiprocessing 子进程重新 import 脚本 "__mp_main__" 替身·入口

导演 NiceGUI 喊:
“只要你是主角,就能启动服务器!”
于是替身不服:
“我穿一样的衣服,为啥不让我开机?”
结果真入口被 if __name__ == "__main__" 拦在门外,替身也进不来,服务器直接罢工。


03 __main__ 到底是干嘛的?

一句话:“防止你写的烂代码在被人 import 时原地爆炸。”

举个栗子:

# cat_launcher.py
def meow():
    print("喵~")

# 测试代码
if __name__ == "__main__":
    meow()          # 只有直接运行才会喵喵叫
  • 直接运行:python cat_launcher.py → 喵喵喵
  • 被别人 import:import cat_launcher → 安静如鸡

这就是“入口守卫” ——
让脚本既能当库,又能当工具,不尴尬。


04 Windows 的彩蛋:替身文学现场

在 Windows 上,multiprocessing 需要“重启”一个 Python 进程,于是:

  1. 重新 import 你的脚本;
  2. __name__ 改成 "__mp_main__"
  3. 如果你的守卫只认 "__main__",替身就被挡在门外;
  4. NiceGUI 检测不到服务器,直接甩锅报错。

05 官方给出的两种“和解方案”

方案 A:拆门——干脆不要守卫

ui.run()  # 谁 import 我,谁直接开服务器

缺点:你室友半夜 import 你一下,服务器被惊醒。

方案 B:发双通行证——替身也放行

if __name__ in {"__main__", "__mp_main__"}:
    ui.run()

真入口 & 替身一起进门,世界和平。


06 彩蛋:一句话记住

写脚本时,__main__ 是“我来主演”;
multiprocessing 时,__mp_main__ 是“我替主演”。
两个都得让进门,否则服务器掀桌子。


07 正解

from nicegui import ui

ui.label('Hello NiceGUI')

if __name__ in {"__main__", "__mp_main__"}:
    ui.run()

下次再遇到“替身文学”,记得给替身也买张门票,别让服务器一个人演独角戏!

posted @ 2025-07-15 00:18  GOKORURI  阅读(21)  评论(0)    收藏  举报