簡體   English   中英

在程序退出時終止在線程中運行的子進程

[英]Terminate subprocess running in thread on program exit

基於這個問題的公認答案: python-subprocess-callback-when-cmd-exits我在一個單獨的線程中運行一個子進程,並在子進程完成后執行一個可調用的。 一切都很好,但問題是,即使將線程作為守護進程運行,即使在程序正常退出或被kill -9 、 Ctrl + C 等殺死后,子進程仍繼續運行......

下面是一個非常簡化的示例(在 2.7 上運行):

import threading
import subprocess
import time
import sys


def on_exit(pid):
    print 'Process with pid %s ended' % pid

def popen_with_callback(cmd):

    def run_in_thread(command):
        proc = subprocess.Popen(
            command,
            shell=False
        )
        proc.wait()
        on_exit(proc.pid)
        return

    thread = threading.Thread(target=run_in_thread, args=([cmd]))
    thread.daemon = True
    thread.start()
    return thread

if __name__ == '__main__':
    popen_with_callback(
        [
            "bash", 
            "-c",
            "for ((i=0;i<%s;i=i+1)); do echo $i; sleep 1; done" % sys.argv[1]
        ])
    time.sleep(5)
    print 'program ended'

如果主線程持續時間比子進程長,一切都很好:

(venv)~/Desktop|➤➤ python testing_threads.py 3
> 0
> 1
> 2
> Process with pid 26303 ended
> program ended

如果主線程持續時間少於子進程,則子進程繼續運行直到它最終掛起:

(venv)~/Desktop|➤➤ python testing_threads.py 8
> 0
> 1
> 2
> 3
> 4
> program ended
(venv)~/Desktop|➤➤ 5
> 6
> 7
# hanging from now on

如果主程序完成或被殺死,如何終止子進程? 我嘗試在 proc.wait 之前使用 atexit.register(os.kill(proc.pid, proc.wait atexit.register(os.kill(proc.pid, signal.SIGTERM))但它實際上是在運行子進程的線程退出時執行的,而不是在線程退出時執行的。

我也在考慮輪詢父 pid,但由於proc.wait情況,我不確定如何實現它。

理想的結果是:

(venv)~/Desktop|➤➤ python testing_threads.py 8
> 0
> 1
> 2
> 3
> 4
> program ended
> Process with pid 1234 ended

使用Thread.join方法,該方法將阻塞主線程,直到該線程退出:

if __name__ == '__main__':
    popen_with_callback(
        [
            "bash", 
            "-c",
            "for ((i=0;i<%s;i=i+1)); do echo $i; sleep 1; done" % sys.argv[1]
        ]).join()
    print 'program ended'

我只是得到了一個丑陋但有效的方法。
只需設置一個全局變量來處理 proc=subprocess.Popen(),
你可以隨時殺死 proc:

my_proc = None

def popen_with_callback(cmd):
  def run_in_thread(command):
    global my_proc
    proc = subprocess.Popen(command, shell=False)
    my_proc = proc
    proc.wait()
    on_exit(proc.pid)
    return
...

然后你可以在程序中任何你想要的地方殺死proc。 做就是了:

my_proc.kill()

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM