git进程作为Python子进程运行时永远不会退出

dm7nw8vv  于 2023-01-06  发布在  Python
关注(0)|答案(1)|浏览(161)

背景

我正在写一个Python程序来处理LFS错误信息,因为我在Bitbucket Server中有一些丢失了LFS文件的repo。当你想找出一个repo中丢失了哪些LFS文件时,运行git lfs fetch --all的输出不是很有帮助。这就是为什么我在为它做一个工具。也许当我完成它时,它可以以某种形式贡献给git项目?

代码片段

import subprocess

def git_lfs_fetch(repo_dir) -> list:
    timeout_sec = 120
    try:
        completed_process = subprocess.run(
            ["git", "lfs", "fetch", "--all"], check=False, cwd=repo_dir, 
            capture_output=True, text=True, timeout=timeout_sec, shell=False)
        return completed_process.stderr.split('\n')
    except subprocess.TimeoutExpired as ex:
        print(f'ERROR Could not complete "{ex.cmd}" before timeout of {timeout_sec} s!')
        print(ex.stderr)
        return []

环境

  • Windows 10,64位
  • Python 3.10.7语言
  • git版本2.35.2.windows操作系统
  • git-lfs/3.0.2版本(GitHub; windows amd64;参见1.17.2)

问题

有时候,subprocess.run()方法永远不会返回,因为git-lfs进程永远不会退出。通常,在我的测试存储库中运行git lfs fetch --all命令需要几秒钟才能完成。作为一种解决方案,我向subprocess.run()调用添加了一个2分钟的timeout。我认为可以从异常的stderr获得我感兴趣的输出。因为git-lfs已经完成了它应该做的所有事情。然而,这并没有帮助。Python似乎不能杀死git子进程。我从文档中了解到,它向进程发送一个SIGKILL,然后等待它退出。但它从未退出,即使设置了超时。
如果我从外部手动终止git-lfs进程,我会从ex.stderr打印预期的输出,所以git-lfs看起来确实像是完成了,我的解决方案做了它应该做的事情。

修复我的工作区

当我以典型的rubberducking方式写这篇文章时,我有了一个想法。
因为Python无法强制终止git子进程,所以我尝试直接使用git-lfs,而不是让git调用它,这样超时就起作用了。

subprocess.run(["git-lfs", "fetch", "--all"], ...)

我在寻找什么

我所寻找的解决方案是一种方法来找出为什么git-lfsgit不能正确终止,更好的是解决这个问题。
我在Linux和Windows上从Java和C#调用git时遇到过类似的问题(几年前),也就是说,git命令实际上完成了它应该完成的所有任务,但是git进程却没有终止。所以我认为这个"挂起"可能是git本身的问题。我真的很想知道为什么git-lfs进程没有终止。我不知道从哪里开始找。

hfyxw5xn

hfyxw5xn1#

通过使用这种方法

def git_lfs_fetch(repo_dir) -> list:
    timeout_sec = 120
    try:
        completed_process = subprocess.run(
            ["git", "lfs", "fetch", "--all"], check=False, cwd=repo_dir, 
            capture_output=True, text=True, timeout=timeout_sec, shell=False)
        return completed_process.stderr.split('\n')
    except subprocess.TimeoutExpired as ex:
        print(f'ERROR Could not complete "{ex.cmd}" before timeout of {timeout_sec} s!')
        print(ex.stderr)
        return []

相关问题