如何使用Python的subprocess.Popen()在执行git命令时检测git挂起

9 浏览
0 Comments

如何使用Python的subprocess.Popen()在执行git命令时检测git挂起

以下是运行任意命令并返回其stdout数据,或在非零退出码时抛出异常的Python代码:

proc = subprocess.Popen(
    cmd,
    stderr=subprocess.STDOUT,  # 合并stdout和stderr
    stdout=subprocess.PIPE,
    shell=True)

使用`communicate`方法等待进程退出:

stdoutdata, stderrdata = proc.communicate()

`subprocess`模块不支持超时(即在运行超过X秒的进程上终止它的能力),因此`communicate`可能需要很长时间才能运行。

在一个旨在在Windows和Linux上运行的Python程序中,实现超时的最简单方法是什么?

0
0 Comments

问题的出现的原因:在执行git命令时,有时会出现卡住的情况,即进程无法正常结束。

解决方法:通过在Python中使用subprocess.Popen()函数来检测git命令卡住的情况,并进行处理。具体的解决方法如下:

1. 创建一个Command类,用于执行git命令。

2. 在Command类中定义一个run()方法,接收一个超时参数。

3. 在run()方法中,创建一个target()函数,用于在单独的线程中执行git命令。

4. 在target()函数中,使用subprocess.Popen()函数来执行git命令,并使用communicate()方法与子进程进行通信。

5. 在run()方法中,创建一个线程,并将target()函数作为target参数传入。

6. 在run()方法中,使用join()方法等待线程执行完毕。

7. 判断线程是否仍在运行,如果是,则调用terminate()方法终止进程。

8. 打印进程的返回码。

以上是通过在单独的线程中执行git命令来检测卡住情况的解决方法。这种方法可以在不同的操作系统上使用,并且可以正常工作。在测试中,该方法在Linux和Windows上都可以正常工作。

但是需要注意的是,在Windows上使用shell=True参数时,需要使用subprocess.Popen("TASKKILL /F /PID {pid} /T".format(pid=self.process.pid))来终止进程。

0
0 Comments

如何使用Python的subprocess.Popen()检测git命令执行时的挂起

当使用subprocess.Popen()执行git命令时,有时候会遇到命令挂起的情况。下面是一个使用threading.Timer类简化jcollado的答案的示例代码:

import shlex
from subprocess import Popen, PIPE
from threading import Timer
def run(cmd, timeout_sec):
    proc = Popen(shlex.split(cmd), stdout=PIPE, stderr=PIPE)
    timer = Timer(timeout_sec, proc.kill)
    try:
        timer.start()
        stdout, stderr = proc.communicate()
    finally:
        timer.cancel()
# Examples: both take 1 second
run("sleep 1", 5)  # process ends normally at 1 second
run("sleep 5", 1)  # timeout happens at 1 second

这个解决方法简单且可移植。不需要使用lambda表达式,只需要使用Timer类的构造函数即可。

有人问为什么需要使用lambda表达式,其实不需要,可以直接使用绑定的proc.kill方法。

另外,有人要求提供一个使用示例,这里提供了两个示例。

有人反馈说jcollado的答案对他而言可行,但是这个解决方法在Windows 7上不起作用。

还有人说这个方法对他而言可行,但是在Windows上只能杀死父进程,不能杀死子进程。

有人发现当Popen的shell参数设置为True时,这个解决方法不起作用,请有人解释一下。

还有人在使用较短的定时器测试这段代码时发现了一个问题。在"finally"语句块中,需要将"timer.cancel()"方法包装在它自己的try/except语句中。在极少数情况下,当进程在代码执行之前被杀死时,可能会出现错误。代码示例如下:

finally:
    try:
        timer.cancel()
    except OSError as e:
        if 'No such process' not in str(e):
            raise OSError(e)

有人问如何判断进程是正常结束还是超时结束,可以在调用`timer.cancel()`之前使用`timer.isAlive()`方法判断。如果返回False,则表示进程正常结束。

这样,我们就可以使用Python的subprocess.Popen()和threading.Timer来检测git命令执行时是否挂起了。

0
0 Comments

问题的出现原因:

- 使用subprocess.Popen()执行git命令时,可能会导致git命令hang住,即无法正常执行和返回结果。

解决方法:

- 在Python 3.3+版本中,可以使用subprocess.check_output()方法来执行git命令,并设置timeout参数来限制命令执行的时间。

- check_output()方法会返回一个包含命令输出的字节字符串。

- 如果命令执行时出现非零的退出状态,check_output()方法会引发CalledProcessError异常。

- 需要注意的是,不要使用shell=True参数,除非命令确实需要该参数。如果使用了shell=True参数,check_output()方法可能会比timeout指定的时间更晚返回结果。

- 若要在Python 2.x版本中使用timeout功能,可以使用subprocess32模块的subprocess32.check_output()方法。

其他相关信息:

- 在Python 3.5+版本中,可以使用subprocess.run()方法并设置capture_output=True参数来执行git命令,并使用encoding参数来获取有用的输出。

- check_output()是获取输出的首选方法,它直接返回输出结果,不会忽略错误,而且一直可用。

- run()方法更加灵活,但默认情况下会忽略错误,需要额外的步骤才能获取输出。

- check_output()方法是基于run()方法实现的,因此接受大部分相同的参数。

- capture_output参数从Python 3.7版本开始可用,而不是3.5版本。

以上是关于如何使用Python的subprocess.Popen()来检测git命令hang住的原因和解决方法的整理。

0