如何在不持续检查标志的情况下终止Python线程

4
class My_Thread(threading.Thread):

    def __init__(self):
        threading.Thread.__init__(self)

    def run(self):
        print "Starting " + self.name
        cmd = [ "bash", 'process.sh']
        p = subprocess.Popen(cmd,
                     stdout=subprocess.PIPE,
                     stderr=subprocess.STDOUT)
        for line in iter(p.stdout.readline, b''):
            print ("-- " + line.rstrip())
        print "Exiting " + self.name

    def stop(self):
        print "Trying to stop thread "
        self.run = False

thr = My_Thread()
thr.start()
time.sleep(30)
thr.stop()
thr.join()

我有一个线程,就像上面展示的一样,实际上在Windows上工作,并且process.sh是在cygwin中运行的bash脚本,需要大约5分钟才能完成执行,因此它不是循环而是一些模拟过程。

我想在这个类中创建stop()函数,以便在需要时立即终止脚本。终止后,我不希望从process.sh脚本中得到任何有用的结果。

请您提供任何方法,如果可能,请稍微解释一下。


可能是如何在Python中终止线程?的重复问题。 - Trevor Boyd Smith
2个回答

10

针对您的特定示例,最简单的方法可能是通过使用 Popen 对象的 terminate() 方法终止由其生成的子进程来终止线程...

class My_Thread(threading.Thread):

    def __init__(self):
        threading.Thread.__init__(self)
        self.process = None

    def run(self):
        print "Starting " + self.name
        cmd = [ "bash", 'process.sh']
        self.process = p = subprocess.Popen(cmd,
                     stdout=subprocess.PIPE,
                     stderr=subprocess.STDOUT)
        for line in iter(p.stdout.readline, b''):
            print ("-- " + line.rstrip())
        print "Exiting " + self.name

    def stop(self):
        print "Trying to stop thread "
        if self.process is not None:
            self.process.terminate()
            self.process = None

thr = My_Thread()
thr.start()
time.sleep(30)
thr.stop()
thr.join()

...导致向 bash 发送 SIGTERM 信号,并且下一次调用 p.stdout.readline() 会引发异常,从而终止线程。


但它会停止后台运行的bash进程还是只是避免在控制台上打印? - Ganesh Gore
它将发送 SIGTERMbash,导致 bash 终止。 - Aya
我如何从拥有我的Tkinter GUI按钮的其他类中调用这个stop()函数? - Ganesh Gore
有趣的事情:你的代码有效,但显示错误消息,称“全局名称'subprocess'未定义”。当我执行import subprocess时,不会出现错误,但是无法正常工作。怎么回事?哈哈 - George
显示剩余2条评论

6

Python的线程不容易被终止,您可以使用几乎相同并且有terminate()函数用于杀死进程的multiprocessing模块(http://docs.python.org/2/library/multiprocessing.html)。

这里有一个小例子,摘自Python文档。

>>> import multiprocessing, time, signal
>>> p = multiprocessing.Process(target=time.sleep, args=(1000,))
>>> print p, p.is_alive()
<Process(Process-1, initial)> False
>>> p.start()
>>> print p, p.is_alive()
<Process(Process-1, started)> True
>>> p.terminate()
>>> time.sleep(0.1)
>>> print p, p.is_alive()
<Process(Process-1, stopped[SIGTERM])> False
>>> p.exitcode == -signal.SIGTERM
True

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接