Хотите завершить подпроцесс, когда поток убит в Python - PullRequest
0 голосов
/ 28 декабря 2018

У меня есть такой код (не тестировался):

import subprocess
import threading 

t1 = threading.Thread(target=start_collect) 

def start_collect():
  process = subprocess.Popen("some command to collect data", stdout=subprocess.PIPE, stderr=subprocess.PIPE)

Теперь мой основной поток и поток t1 в какой-то момент уничтожаются, в то время как подпроцесс все еще выполняет свою команду, собирая данные.Я хочу, чтобы он прекратил выполнение этой команды и уничтожил подпроцесс.Поэтому, когда мой родительский поток (поток, вызывающий подпроцесс) будет уничтожен, я хочу уничтожить подпроцесс.Есть ли способ сделать это?

1 Ответ

0 голосов
/ 28 декабря 2018

Таким образом, Thread будет выполняться до тех пор, пока он не будет соединен, поэтому мы должны попросить его как-нибудь уйти.Как уже упоминалось, я бы, вероятно, создал его подкласс и создал бы методы, которые позволили бы аккуратно ссылаться на подпроцесс, который он мог порождать, и грациозно завершать его следующим образом:

class InterruptibleThread(Thread):
    def __init__(self, target):
        super().__init__()
        self.target = target
        self.process = None
        self._stopevent = Event()
        self._periodicity = 1.0
    def run(self):
        self.process = Popen(self.target)
        while not self._stopevent.is_set():
            self._stopevent.wait(self._periodicity)
    def stop(self):
        self._stopevent.set()
        self.process.terminate()
        Thread.join(self)

Я на машине с Windows, поэтомуСледующая последовательность открывает окно командной строки и завершается, когда порожденный поток имеет вызванный метод stop():

>>> t = InterruptibleThread('cmd')
>>> t.target
'cmd'
>>> t.process # Returns None as it should
>>> t.start()
>>> t.process
<subprocess.Popen object at 0x00000295ACC704E0>
>>> t.process.poll() # Returns None as it should
>>> t.stop()
>>> t.process.poll()
1
>>>

Теперь в вашей программе, вероятно, есть логика, которая требует от вас t.join()Это нормально, здесь я просто принудительно использую t.stop(), который в конечном итоге присоединяется к потоку, так что ваши программы вызывают t.join(), либо переопределяя метод join(), либо где-то еще в вашей программе, вызывая определенный t.stop().t.process.poll() проверяет, завершен ли процесс (просто показан здесь для демонстрационных целей).Итак, теперь у вас есть способ завершить поток и его подпроцессы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...