无法捕获UploadRobot.run()抛出的fileexists-no-change APIError求助
解决pywikibot UploadRobot无法捕获fileexists-no-change异常的问题
问题背景
使用pywikibot的UploadRobot向维基共享资源上传文件时,遇到文件已存在的场景会抛出pywikibot.exceptions.APIError: fileexists-no-change,但尝试外层try/except、post_processor回调、全局异常处理钩子均无法捕获该异常,日志显示异常被抛出后脚本仍提示“Script terminated successfully”,无法自定义处理重复文件场景。
原因分析
pywikibot的UploadRobot内部(specialbots/_upload.py的upload_file方法)已捕获APIError,仅记录日志但不会重新抛出异常,因此外层异常处理机制无法感知;同时post_processor的触发逻辑未覆盖fileexists-no-change这类场景,导致回调无法生效。
解决方案
方法一:上传前预检查文件是否存在
在调用UploadRobot前,先构造FilePage对象检查目标文件是否已存在,提前处理重复场景:
import sys import pywikibot from pywikibot.specialbots import UploadRobot # 初始化维基共享资源站点 site = pywikibot.Site('commons', 'commons') def check_file_exists(target_filename): """检查目标文件是否已存在于维基共享资源""" file_page = pywikibot.FilePage(site, target_filename) return file_page.exists() # 提取本地文件的目标文件名(根据实际路径调整) local_file_path = sys.argv[1] target_filename = local_file_path.split('/')[-1] # 预检查逻辑 if check_file_exists(target_filename): print(f"⚠️ 文件 {target_filename} 已存在,跳过上传") else: # 初始化UploadRobot并执行上传 bot = UploadRobot( local_file_path, description=description, keep_filename=True, ignore_warning=True, target_site=site, summary=summary, always=True ) bot.run()
方法二:子类化UploadRobot,重写异常处理逻辑
通过继承UploadRobot,重写upload_file方法,自定义捕获fileexists-no-change异常的处理逻辑:
import sys import pywikibot from pywikibot.specialbots import UploadRobot from pywikibot.exceptions import APIError class CustomUploadRobot(UploadRobot): def upload_file(self, file_url, title=None): try: # 调用父类的上传逻辑 return super().upload_file(file_url, title) except APIError as e: if e.code == 'fileexists-no-change': # 自定义重复文件的处理逻辑 print(f"⚠️ 上传失败:文件已存在 - {e}") return None # 返回None可触发post_processor的失败分支 else: # 其他API异常原样抛出,由外层处理 raise # 使用自定义机器人执行上传 bot = CustomUploadRobot( sys.argv[1], description=description, keep_filename=True, ignore_warning=True, target_site=pywikibot.Site('commons', 'commons'), summary=summary, always=True, post_processor=lambda file_url, filename: print(f"✅ 上传成功: {filename}" if filename else f"⚠️ 处理失败: {file_url}") ) try: bot.run() except APIError as e: print(f"未处理的API错误: {e}")
方法三:监听pywikibot日志消息
利用pywikibot的日志系统,捕获包含fileexists-no-change的日志输出,实现自定义处理:
import logging import sys import pywikibot from pywikibot.specialbots import UploadRobot # 自定义日志处理器 class DuplicateFileHandler(logging.Handler): def emit(self, record): if 'fileexists-no-change' in record.getMessage(): print(f"⚠️ 检测到重复文件: {record.getMessage()}") # 添加处理器到pywikibot的日志器 logger = logging.getLogger('pywikibot') logger.addHandler(DuplicateFileHandler()) # 初始化并运行UploadRobot bot = UploadRobot( sys.argv[1], description=description, keep_filename=True, ignore_warning=True, target_site=pywikibot.Site('commons', 'commons'), summary=summary, always=True ) bot.run()
内容的提问来源于stack exchange,提问作者Vitaly Zdanevich
相关产品推荐
相关产品推荐

