如何在Python Rumps应用中后台运行文件传输与请求进程?
解决Rumps应用因后台耗时操作冻结的问题
问题根源
Rumps的Timer回调函数运行在UI主线程中,S3上传、HTTP请求这类耗时操作会阻塞UI事件循环,直接导致应用冻结无响应。
解决方案:用线程后台执行耗时操作
直接用Python的threading模块把上传和请求逻辑放到独立线程中,完全不阻塞主线程。修改后的代码示例:
import threading import os import requests import rumps import boto3 class MyApp(rumps.App): def __init__(self): super(MyApp, self).__init__("App", quit_button="Stop") self.process_folder = "/your/target/folder" # 替换为实际监控路径 self.s3_client = boto3.client('s3') self.files_in_folder = set() self.process_timer = rumps.Timer(self.my_tick, 1) self.process_timer.start() def _handle_new_file(self, new_file): """后台执行的文件处理逻辑""" fullpath = os.path.join(self.process_folder, new_file) try: # 上传到S3 self.s3_client.upload_file( fullpath, '##bucket##', f'##key_prefix##/{new_file}' # 建议添加前缀避免文件重名 ) # 发送GET请求 requests.get( '##url##', params={'file': new_file} ) except Exception as e: # 可添加错误日志或桌面通知 print(f"处理文件 {new_file} 失败: {str(e)}") def my_tick(self, sender): named_set = set() for file in os.listdir(self.process_folder): fullpath = os.path.join(self.process_folder, file) if os.path.isfile(fullpath) and fullpath.lower().endswith('.jpg'): named_set.add(file) if not named_set: self.files_in_folder = set() return new_files = sorted(named_set - self.files_in_folder) if new_files: for new_file in new_files: # 启动后台线程处理文件,不阻塞UI主线程 threading.Thread(target=self._handle_new_file, args=(new_file,), daemon=True).start() self.files_in_folder = named_set if __name__ == "__main__": MyApp().run()
关键改动说明
- 把耗时的上传、请求逻辑抽成独立方法
_handle_new_file - 在
my_tick中用threading.Thread启动后台线程,daemon=True确保线程随主程序退出自动结束 - 修复原代码中
return requests.get(...)导致循环提前终止的问题(原代码处理第一个文件后就停止,后续文件无法处理)
关于subprocess失效的排查方向
你之前用subprocess.Popen没生效,大概率是路径问题:
- 用
sys.executable代替python3,确保调用当前环境的Python解释器 - 指定
transferscript.py的绝对路径,避免Rumps找不到脚本 - 添加输出重定向排查子进程错误:
import sys import subprocess # 替换原subprocess调用 proc = subprocess.Popen( [sys.executable, "/full/path/to/transferscript.py", new_file], stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True ) # 可将stdout/stderr写入日志文件查看具体错误 with open("subprocess_log.txt", "a") as f: f.write(f"STDOUT: {proc.stdout.read()}\nSTDERR: {proc.stderr.read()}\n")
内容的提问来源于stack exchange,提问作者Schmidty
相关产品推荐
相关产品推荐

