Таким образом, 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()
проверяет, завершен ли процесс (просто показан здесь для демонстрационных целей).Итак, теперь у вас есть способ завершить поток и его подпроцессы.