如何避免os.system调用时创建多Python进程并保持脚本正常循环
问题核心原因
- 代码触发双层
if判断后直接调用了os.exit(),该方法会立即终止当前Python主进程,后续循环逻辑完全不会执行,这是程序直接退出的直接原因。 - 对
os.system()的行为存在误解:传入执行osascript弹窗的命令时,只会创建独立的osascript子进程完成通知展示,不会创建新的Python进程。此前测试出现新Python进程,是主动传入os.system("python3 script.py")命令拉起的新脚本实例,和os.system()本身无关。 - 此前测试的
sys.exit()、主动给自身pid发SIGKILL信号的逻辑,全都是主动终止当前进程的操作,必然导致脚本直接退出,不可能实现回到循环的效果。
修正方法
直接删除分支内所有主动退出进程、重新拉起Python脚本的代码,通知逻辑执行完成后,代码会自然回到while True循环的下一轮,完全不需要做进程级的退出/重启操作。
同时做两点优化:
- 把重复的蓝牙状态查询逻辑抽为公共函数,减少冗余代码
- 统一用已经在使用的
subprocess.run执行弹窗命令,替代os.system,避免特殊字符导致的shell解析问题
修正后的完整代码如下:
import time import subprocess def get_bluetooth_state(): """查询当前蓝牙状态,返回命令输出文本""" ret = subprocess.run( ["system_profiler", "SPBluetoothDataType"], capture_output=True, encoding="utf-8", errors="ignore" ) return ret.stdout def bluetoothLoop(): alert_sound = "Blow" alert_title = "TURN OFF BLUETOOTH" alert_msg = "-------------------------" while True: time.sleep(5) bt_state = get_bluetooth_state() # 首次检测:蓝牙开启且无已连接设备 if "State: On" in bt_state and " Connected:" not in bt_state: time.sleep(1) # 二次确认避免误判 bt_state = get_bluetooth_state() if "State: On" in bt_state and " Connected:" not in bt_state: # 执行弹窗通知,仅创建osascript子进程,不会拉起新Python实例 subprocess.run( ["osascript", "-e", f'display notification "{alert_msg}" with title "{alert_title}" sound name "{alert_sound}"'], timeout=3 # 加超时避免子进程卡死阻塞主循环 ) time.sleep(1) # 若notify.restart()是业务需要的通知模块重置逻辑可保留,禁止加任何退出/拉起新脚本的代码 # notify.restart()
效果说明
修正后程序会持续在循环内运行:每5秒完成一次蓝牙状态检测,满足触发条件时弹出系统通知,之后自动回到循环起点等待下一轮检测,既不会退出当前脚本进程,也不会生成多余的Python运行实例。
不要在循环逻辑内添加任何调用os.exit()/sys.exit()、杀自身进程、执行python3 自身脚本路径的代码,这类操作必然导致进程退出、多实例重复运行的异常。
内容的提问来源于stack exchange,提问作者c0nfluks
相关产品推荐
相关产品推荐

