Python2.6中如何处理异常以保障程序持续运行?
让Python2.6脚本在请求超时后持续运行的解决方案
你的问题核心在于异常捕获的范围错误:当前的try-except包裹了整个监听循环(notifier.loop()),当单个文件处理中的网络请求抛出超时异常时,会直接跳出整个循环,导致程序终止。正确的做法是把异常捕获放在单个文件请求的逻辑内部,这样即使某次请求失败,监听循环依然能继续运行。
具体修改步骤
1. 聚焦请求逻辑的异常处理
你的ModHandler类是处理文件事件的核心(当目录有新文件关闭时触发),需要把网络请求的代码从ModHandler的处理方法中(比如process_default或自定义方法)单独用try-except包裹,确保单个请求的错误不会影响全局循环。
2. 修改请求代码的异常捕获
把原来的请求逻辑改成下面这样,在请求内部针对性捕获错误,写入日志后继续执行:
# 假设这段代码在ModHandler的文件处理方法中 def process_default(self, event): image_file_path = event.pathname try: with open(image_file_path, 'rb') as image_file: encoded_string = base64.b64encode(image_file.read()) values = dumps({ 'image_data':encoded_string, 'requestCode':'111' }) headers = {"Content-Type": "application/json"} # 注意URL补全http://前缀,避免请求错误 request = Request("http://xx.xxx.xx.xxx/api/carplate_service", data=values, headers=headers) response = urlopen(request, timeout=60) # 如需处理响应,可在此添加逻辑 except urllib2.URLError as e: # 捕获超时等URL相关错误 self._log_error(e, sys.exc_info()) except IOError as e: # 捕获文件读取类错误 self._log_error(e, sys.exc_info()) except Exception as e: # 兜底捕获其他意外错误 self._log_error(e, sys.exc_info()) # 新增复用的日志记录方法 def _log_error(self, error, exc_info): exc_type, exc_obj, exc_tb = exc_info fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1] with open("error.log", "a") as text_file: log_msg = "{0} [{1} - {2}] : {3} - {4}\n".format( time.strftime("%Y-%m-%d %H:%M:%S"), exc_tb.tb_lineno, fname, str(exc_type), str(error) ) text_file.write(log_msg)
3. 调整外层异常处理的职责
原来的外层try-except可以保留,但只用来捕获监听循环本身的致命错误(比如初始化失败、监听目录不存在等),不再处理单个请求的错误:
try: ip = sys.argv[1] histId = int(sys.argv[2]) handler = ModHandler() wm = pyinotify.WatchManager() notifier = pyinotify.Notifier(wm, handler) watch_path = './' + ip + '/' # 提前检查目录是否存在,避免初始化阶段失败 if not os.path.isdir(watch_path): raise IOError(f"监听目录 {watch_path} 不存在或不是合法目录") wdd = wm.add_watch(watch_path, pyinotify.IN_CLOSE_WRITE) notifier.loop() except BaseException as e: with open("error.log", "a") as text_file: exc_type, exc_obj, exc_tb = sys.exc_info() fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1] text_file.write( time.strftime("%Y-%m-%d %H:%M:%S") + " [" + str(exc_tb.tb_lineno) + " - " + fname + "] : " + str(exc_type) + " - " + str(e) + "\n" )
额外优化建议
- 增加重试机制:凌晨的超时大概率是服务端维护或网络波动,可以给请求加3次以内的重试,间隔2秒:
max_retries = 3 retry_count = 0 success = False while retry_count < max_retries and not success: try: response = urlopen(request, timeout=60) success = True except urllib2.URLError as e: retry_count += 1 time.sleep(2) if retry_count == max_retries: self._log_error(e, sys.exc_info()) - 日志补充上下文:可以在错误日志中加入当前处理的文件名,方便后续排查具体是哪个文件的请求失败。
内容的提问来源于stack exchange,提问作者Yohanes AI
相关产品推荐
相关产品推荐

