You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python使用pystray时无法正常退出程序的问题求助

问题描述

尝试用exit()、exit(0)、sys.exit()(已导入sys)及quit()退出pystray托盘程序均失败,调用时会抛出SystemExit异常;使用icon.stop()仅能终止托盘图标,后续代码需等托盘退出后才执行,无法直接退出整个程序。

尝试1:使用exit()的代码

from pystray import MenuItem as item
import pystray
from PIL import Image


while True:
    def show():
        exit()
    image = Image.open("TrayIcon.jpg")
    menu = (item('exit', show),)
    icon = pystray.Icon("name", image, "title", menu)
    icon.run()
    print('running...')

报错信息

An error occurred when calling message handler
Traceback (most recent call last):
  File "D:\py3.7\lib\site-packages\pystray\_win32.py", line 402, in _dispatcher
    uMsg, lambda w, l: 0)(wParam, lParam) or 0)
  File "D:\py3.7\lib\site-packages\pystray\_win32.py", line 213, in _on_notify
    descriptors[index - 1](self)
  File "D:\py3.7\lib\site-packages\pystray\_base.py", line 324, in inner
    callback(self)
  File "D:\py3.7\lib\site-packages\pystray\_base.py", line 449, in __call__
    return self._action(icon, self)
  File "D:\py3.7\lib\site-packages\pystray\_base.py", line 544, in wrapper0
    return action()
  File "C:/Users/admin/AppData/Roaming/JetBrains/PyCharmCE2022.1/scratches/scratch.py", line 9, in show
    exit()
  File "D:\py3.7\lib\_sitebuiltins.py", line 26, in __call__
    raise SystemExit(code)
SystemExit: None

尝试2:使用icon.stop()的代码

from pystray import MenuItem as item
import pystray
from PIL import Image


def show():
    icon.stop()


image = Image.open("TrayIcon.jpg")
menu = (item('exit', show),)
icon = pystray.Icon("name", image, "title", menu)
icon.run()

while True:
    print('running...')

现象

托盘图标显示期间无running...输出,必须退出托盘后才开始打印,且无法直接退出整个程序。

解决方案

1. 正确实现程序退出(结合icon.stop()与sys.exit())

pystray的icon.run()是阻塞式方法,会启动消息循环。直接在菜单回调中调用exit()会在消息处理线程中抛出异常,导致报错。正确做法是先停止托盘,再退出程序,同时将后台任务放到守护线程中运行。

修改后代码:

from pystray import MenuItem as item
import pystray
from PIL import Image
import sys
import threading
import time


def background_task():
    # 后台运行的任务逻辑
    while True:
        print('running...')
        time.sleep(1)  # 控制打印频率


def on_exit(icon, item):
    # 先终止托盘消息循环
    icon.stop()
    # 退出整个程序
    sys.exit()


# 启动后台守护线程,主线程退出时自动终止
threading.Thread(target=background_task, daemon=True).start()

image = Image.open("TrayIcon.jpg")
menu = (item('exit', on_exit),)
icon = pystray.Icon("name", image, "title", menu)
icon.run()

2. 关键要点

  • icon.run()会阻塞主线程,因此后台任务必须放在守护线程中,避免主线程被卡住。
  • 菜单回调中先执行icon.stop()停止托盘消息循环,再调用sys.exit()退出程序,避免在消息处理线程中抛出异常。
  • 不要将icon.run()放入while True循环,这会导致托盘被反复创建,造成逻辑混乱。

内容的提问来源于stack exchange,提问作者Danhui Xu

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.22 13:09:29