如何阻止Python中其他线程抛出的Git CommandError异常自动打印
根因说明
你主线程的try/except只能捕获主线程上下文抛出的CommandError,子线程pump_stream内部抛出异常后,Python线程默认的异常处理逻辑会直接把异常栈打印到标准错误流,这部分打印不受主线程异常捕获逻辑控制。
解决方案
方案1:自定义子线程异常钩子(侵入性最低,优先选择)
Python 3.8及以上版本提供了threading.excepthook接口,可以自定义子线程异常的处理逻辑,临时覆盖钩子过滤掉Git相关子线程的异常打印,执行完操作再恢复即可:
import threading import git.exc # 保存默认钩子 original_excepthook = threading.excepthook def silent_git_excepthook(args): # 只过滤Git pump_stream线程抛出的异常,其他异常保持原有打印逻辑 if isinstance(args.exc_value, git.exc.CommandError) or "pump_stream" in str(args.traceback): return original_excepthook(args) # 替换钩子 threading.excepthook = silent_git_excepthook try: # 此处替换为你的Git操作代码 <do something in git that will raise the CommandError exception> except git.exc.CommandError: print('>>>>>>>>>>>>>>>>>>>>>>>>>> I GOT IT') finally: # 恢复默认钩子,避免影响其他业务逻辑 threading.excepthook = original_excepthook
如果是Python 3.7及以下版本,可以通过猴子补丁修改Thread.run方法实现相同效果:
import threading import sys import git.exc from threading import Thread original_run = Thread.run def patched_run(self): try: original_run(self) except Exception as e: if isinstance(e, git.exc.CommandError) or any("pump_stream" in frame.f_code.co_name for frame in sys._current_frames().values()): return raise Thread.run = patched_run try: # 此处替换为你的Git操作代码 <do something in git that will raise the CommandError exception> except git.exc.CommandError: print('>>>>>>>>>>>>>>>>>>>>>>>>>> I GOT IT') finally: Thread.run = original_run
方案2:关闭Git库的错误日志
你贴的Git库代码中首先会输出log.error级别的日志,你可以将Git对应模块的日志级别调高,屏蔽这部分打印:
import logging logging.getLogger('git.cmd').setLevel(logging.WARNING)
该方案可以和方案1配合使用,完全屏蔽Git相关的错误输出。
方案3:临时重定向标准错误流
如果以上方案都不适用,可以临时把标准错误流重定向到空设备,执行完Git操作再恢复,该方案会吞掉执行期间所有的标准错误输出,非必要不推荐:
import os import sys from contextlib import contextmanager @contextmanager def suppress_stderr(): original_stderr = sys.stderr sys.stderr = open(os.devnull, 'w') try: yield finally: sys.stderr.close() sys.stderr = original_stderr try: with suppress_stderr(): # 此处替换为你的Git操作代码 <do something in git that will raise the CommandError exception> except git.exc.CommandError: print('>>>>>>>>>>>>>>>>>>>>>>>>>> I GOT IT')
内容的提问来源于stack exchange,提问作者Sondos.S
相关产品推荐
相关产品推荐

