Python中如何为执行Git命令的subprocess设置超时?
subprocess配置超时的实现方案
方案1:Python 3.6 环境(原生支持timeout参数)
Python 3.5及以上版本的subprocess.run()原生提供timeout参数,单位为秒,执行超过指定时间后会主动终止子进程,并抛出subprocess.TimeoutExpired异常,可直接搭配重试逻辑使用。
修改后的代码示例(包含3次重试逻辑):
#------------------------------------------------------------------------------ # Script to daily build Voyant 3 #------------------------------------------------------------------------------ import subprocess import os import time #------------------------------------------------------------------------------ # 配置参数 #------------------------------------------------------------------------------ repo_dir = "c:/sandboxes/git/voyant-3" MAX_RETRY = 3 # 最大重试次数 FETCH_TIMEOUT = 300 # git fetch超时时间,单位秒,此处设为5分钟 #------------------------------------------------------------------------------ # Main program starts here. #------------------------------------------------------------------------------ os.chdir(repo_dir) # 带重试的git fetch逻辑 success = False for retry_cnt in range(MAX_RETRY): try: subprocess.run( ["git", "fetch", "--all"], timeout=FETCH_TIMEOUT, check=True, # 命令执行非0返回码时会抛出CalledProcessError异常 capture_output=True, text=True ) success = True break except subprocess.TimeoutExpired: print(f"git fetch 超时,第{retry_cnt+1}次重试") except subprocess.CalledProcessError as e: print(f"git fetch 执行失败,错误信息:{e.stderr},第{retry_cnt+1}次重试") time.sleep(10) # 重试前等待10秒 if not success: print(f"git fetch 经过{MAX_RETRY}次尝试后仍失败,退出构建") exit(1) # 后续构建逻辑
方案2:Python 2.7 环境(自定义超时逻辑)
Python 2.7的subprocess没有原生timeout参数,可通过subprocess.Popen配合计时轮询实现超时控制,适配Windows 10环境:
#------------------------------------------------------------------------------ # Script to daily build Voyant 3 #------------------------------------------------------------------------------ import subprocess import os import time import sys #------------------------------------------------------------------------------ # 配置参数 #------------------------------------------------------------------------------ repo_dir = "c:/sandboxes/git/voyant-3" MAX_RETRY = 3 # 最大重试次数 FETCH_TIMEOUT = 300 # git fetch超时时间,单位秒,此处设为5分钟 # 自定义超时异常,适配Python2.7 class TimeoutExpired(Exception): pass #------------------------------------------------------------------------------ # 带超时的subprocess执行方法 #------------------------------------------------------------------------------ def run_with_timeout(args, timeout): proc = subprocess.Popen(args, stderr=subprocess.PIPE, stdout=subprocess.PIPE) start_time = time.time() while proc.poll() is None: time.sleep(1) if time.time() - start_time > timeout: proc.kill() proc.wait() raise TimeoutExpired(f"Command {' '.join(args)} timed out after {timeout} seconds") stdout, stderr = proc.communicate() return proc.returncode, stdout, stderr #------------------------------------------------------------------------------ # Main program starts here. #------------------------------------------------------------------------------ os.chdir(repo_dir) # 带重试的git fetch逻辑 success = False for retry_cnt in range(MAX_RETRY): try: returncode, stdout, stderr = run_with_timeout(["git", "fetch", "--all"], FETCH_TIMEOUT) if returncode != 0: print(f"git fetch 执行失败,错误信息:{stderr},第{retry_cnt+1}次重试") time.sleep(10) continue success = True break except TimeoutExpired as e: print(f"{e},第{retry_cnt+1}次重试") time.sleep(10) if not success: print(f"git fetch 经过{MAX_RETRY}次尝试后仍失败,退出构建") sys.exit(1) # 后续构建逻辑
注意事项
- 代码中已修复原示例里
["git", "fetch", "--all]"]多写的多余右括号问题 - 超时时间可根据仓库实际大小调整,若仓库体积大、网络较慢可适当延长
- Windows环境下注册为系统服务运行时,建议配置日志输出,方便排查超时、执行失败的原因
内容的提问来源于stack exchange,提问作者Thomas Matthews
相关产品推荐
相关产品推荐

