使用Python Subprocess.call打开多个Mac应用的问题及优化需求
解决Mac下Python脚本启动应用的阻塞与路径问题
核心问题梳理
你遇到的几个关键问题:
- 直接用
subprocess.call会阻塞脚本,直到应用关闭才执行后续代码 - 带空格的应用路径在不用
shell=True时的解析问题 - 需要等待应用加载完成而非关闭后再继续执行脚本
解决方案代码
方法1:用psutil检查进程加载状态(需额外安装库)
先安装依赖:
pip install psutil
脚本实现:
import subprocess import psutil import time def wait_app_loaded(target_process_name): """等待应用进程启动并进入稳定状态""" while True: for proc in psutil.process_iter(["name", "status"]): if proc.info["name"] == target_process_name and proc.info["status"] == psutil.STATUS_RUNNING: # 通过内存变化判断是否加载完成(内存波动小于10%视为稳定) mem_initial = proc.memory_info().rss time.sleep(2) mem_latest = proc.memory_info().rss if abs(mem_latest - mem_initial) < mem_initial * 0.1: return time.sleep(1) # 启动Google Chrome(非阻塞,无需shell=True) print("启动Chrome...") chrome_proc = subprocess.Popen( ["/Applications/Google Chrome.app/Contents/MacOS/Google Chrome"], stdout=subprocess.DEVNULL, stderr=subprocess.STDOUT ) wait_app_loaded("Google Chrome") print("Chrome加载完成,继续执行") # 启动MongoDB Compass print("启动MongoDB Compass...") compass_proc = subprocess.Popen( ["/Applications/MongoDB Compass.app/Contents/MacOS/MongoDB Compass"], stdout=subprocess.DEVNULL, stderr=subprocess.STDOUT ) wait_app_loaded("MongoDB Compass") print("所有应用加载完成")
方法2:用系统自带AppleScript检查(无需额外安装)
利用Mac原生的AppleScript判断应用是否就绪:
import subprocess def wait_app_ready(app_display_name): """通过AppleScript等待应用启动并就绪""" script = f''' tell application "{app_display_name}" repeat until it is running delay 1 end repeat repeat until frontmost of it is true delay 1 end repeat end tell ''' subprocess.run(["osascript", "-e", script], capture_output=True) # 启动Chrome chrome_proc = subprocess.Popen( ["/Applications/Google Chrome.app/Contents/MacOS/Google Chrome"], stdout=subprocess.DEVNULL, stderr=subprocess.STDOUT ) wait_app_ready("Google Chrome") print("Chrome已就绪") # 启动MongoDB Compass compass_proc = subprocess.Popen( ["/Applications/MongoDB Compass.app/Contents/MacOS/MongoDB Compass"], stdout=subprocess.DEVNULL, stderr=subprocess.STDOUT ) wait_app_ready("MongoDB Compass") print("MongoDB Compass已就绪")
关键说明
- 替换
subprocess.call为Popen:call会等待子进程结束才返回,而Popen会立即启动进程并返回进程对象,实现非阻塞启动 - 路径处理:用列表形式传入命令参数,无需转义空格,直接写
"/Applications/Google Chrome.app/Contents/MacOS/Google Chrome"即可,避免shell=True的安全风险和路径转义问题 - 等待加载完成:
- 方法1通过
psutil监控进程状态和内存变化,判断应用是否完成加载 - 方法2利用AppleScript检查应用是否运行并处于前台,适合依赖GUI状态的应用
- 方法1通过
- 输出重定向:
stdout=subprocess.DEVNULL和stderr=subprocess.STDOUT会屏蔽应用的终端输出,避免占用终端窗口
内容的提问来源于stack exchange,提问作者user8758206
相关产品推荐
相关产品推荐

