GVKun编程网logo

终止多线程python程序(python停止多线程)

8

对于想了解终止多线程python程序的读者,本文将是一篇不可错过的文章,我们将详细介绍python停止多线程,并且为您提供关于Linux下后台运行和终止python程序常用命令、Python中用Ctr

对于想了解终止多线程python程序的读者,本文将是一篇不可错过的文章,我们将详细介绍python停止多线程,并且为您提供关于Linux下后台运行和终止python程序常用命令、Python 中用 Ctrl+C 终止多线程程序的问题解决、Python中用Ctrl+C终止多线程程序的问题解决、Python基础一(认识Python、搭建编程环境、第一个Python程序)的有价值信息。

本文目录一览:

终止多线程python程序(python停止多线程)

终止多线程python程序(python停止多线程)

如何使多线程python程序响应Ctrl + C键事件?

编辑: 代码是这样的:

import threadingcurrent = 0class MyThread(threading.Thread):    def __init__(self, total):        threading.Thread.__init__(self)        self.total = total    def stop(self):        self._Thread__stop()    def run(self):        global current        while current<self.total:            lock = threading.Lock()            lock.acquire()            current+=1            lock.release()            print currentif __name__==''__main__'':    threads = []    thread_count = 10    total = 10000    for i in range(0, thread_count):        t = MyThread(total)        t.setDaemon(True)        threads.append(t)    for i in range(0, thread_count):        threads[i].start()

我试图在所有线程上删除join(),但仍然无法正常工作。是否因为每个线程的run()过程中的锁段?

编辑: 上面的代码应该可以工作,但是当当前变量在5,000-6,000范围内并遍历以下错误时,它总是会中断

Exception in thread Thread-4 (most likely raised during interpreter shutdown):Traceback (most recent call last):  File "/usr/lib/python2.5/threading.py", line 486, in __bootstrap_inner  File "test.py", line 20, in run<type ''exceptions.TypeError''>: unsupported operand type(s) for +=: ''NoneType'' and ''int''Exception in thread Thread-2 (most likely raised during interpreter shutdown):Traceback (most recent call last):  File "/usr/lib/python2.5/threading.py", line 486, in __bootstrap_inner  File "test.py", line 22, in run

答案1

小编典典

在启动主线程之前,将除主线程之外的每个线程都设为守护进程(t.daemon =True在2.6或更高版本中,t.setDaemon(True)在2.6或更低版本中,针对每个线程对象t)。这样,当主线程收到KeyboardInterrupt时,如果它没有捕获到或捕获到它,但是无论如何都决定终止,则整个过程将终止。请参阅文档。

编辑 :刚刚看过OP的代码(最初未发布)和声称“它不起作用”,看来我必须添加…:

当然,如果你希望你的主线程保持响应(例如,为了控制-C),不泥潭成阻塞调用,如join荷兰国际集团另一个线程-尤其是没有完全 无用的
阻塞调用,如join荷兰国际集团 守护 线程。例如,仅更改当前线程在主线程中的最终循环(完全无损):

for i in range(0, thread_count):    threads[i].join()

像这样更明智:

while threading.active_count() > 0:    time.sleep(0.1)

如果您的main没有比将所有线程自己终止或接收control-C(或其他信号)更好的事情了。

当然,如果您不想让线程突然终止(如守护线程可能),还有许多其他可用的模式-除非 它们 也被永久地陷入无条件阻塞的调用,死锁等;-) 。

Linux下后台运行和终止python程序常用命令

Linux下后台运行和终止python程序常用命令

后台运行python程序

  • 后台运行程序

运行test.py,标准输出(运行记录)保存在log.txt中

nohup python -u test.py > log.txt 2>&1 & 

nohup是no hang up,& 是后台运行,两者结合可以在用户退出时,保持后台运行

-u 是不启用缓存,不然的话print重定向写入文件的过程会有缓存,log.txt文件不会实时更新

2>&1 错误重定向到标准输出

终止程序运行

  • 观察GPU使用情况

在实验的过程中,我们可能会因为代码bug等各种原因,希望提前停止在后台运行的程序。但是此时可能你已经记不清后台运行的多个程序中,哪一个是我们想要停止的程序。此时可以先通过观察GPU的使用情况命令,获取正在GPU上运行的程序的pid。

 watch -n 1 nvidia-smi
  • 根据pid查看对应的程序

在或许到后台运行的程序的pid集合后,我们可以通过以下命令查看每个pid对应的程序,运行后会输出我们运行程序使用的命令以及命令行参数,从而找到需要提前终止的程序。

ps -ef|grep 16923
  • 终止程序

假设pid为16923的程序就是我们希望提前终止的程序,那么我们使用以下命令提前终止程序的运行。

kill -9 16923

Python 中用 Ctrl+C 终止多线程程序的问题解决

Python 中用 Ctrl+C 终止多线程程序的问题解决

花了一天时间用python为服务写了个压力测试。很简单,多线程向服务器发请求。但写完之后发现如果中途想停下来,按Ctrl+C达不到效果,自然想到要用信号处理函数捕捉信号,使线程都停下来,问题解决的方法请往下看:

#!/bin/env python
# -*- coding: utf-8 -*-
#filename: peartest.py

import threading, signal

is_exit = False

def doStress(i, cc):
    global is_exit
    idx = i
    while not is_exit:
    if (idx < 10000000):
        print "thread[%d]: idx=%d"%(i, idx)
        idx = idx + cc
    else:
        break
    print "thread[%d] complete."%i

def handler(signum, frame):
    global is_exit
    is_exit = True
    print "receive a signal %d, is_exit = %d"%(signum, is_exit)

if __name__ == "__main__":
    signal.signal(signal.SIGINT, handler)
    signal.signal(signal.SIGTERM, handler)
    cc = 5
    for i in range(cc):
        t = threading.Thread(target=doStress, args=(i,cc))
        t.start()

上面是一个模拟程序,并不真正向服务发送请求,而代之以在一千万以内,每个线程每隔并发数个(cc个)打印一个整数。很明显,当所有线程都完成自己的任务后,进程会正常退出。但如果我们中途想退出(试想一个压力测试程序,在中途已经发现了问题,需要停止测试),该肿么办?你当然可以用ps查找到进程号,然后kill -9杀掉,但这样太繁琐了,捕捉Ctrl+C是最自然的想法。上面示例程序中已经捕捉了这个信号,并修改全局变量is_exit,线程中会检测这个变量,及时退出。

但事实上这个程序并不work,当你按下Ctrl+C时,程序照常运行,并无任何响应。网上搜了一些资料,明白是python的子线程如果不是daemon的话,主线程是不能响应任何中断的。但设为daemon后主线程会随之退出,接着整个进程很快就退出了,所以还需要在主线程中检测各个子线程的状态,直到所有子线程退出后自己才退出,因此上例29行之后的代码可以修改为:

threads=[]
for i in range(cc):
    t = threading.Thread(target=doStress, args=(i, cc))
    t.setDaemon(True)
    threads.append(t)
    t.start()
for i in range(cc):
    threads[i].join()

重新试一下,问题依然没有解决,进程还是没有响应Ctrl+C,这是因为join()函数同样会waiting在一个锁上,使主线程无法捕获信号。因此继续修改,调用线程的isAlive()函数判断线程是否完成:

while 1:
    alive = False
    for i in range(cc):
        alive = alive or threads[i].isAlive()
    if not alive:
    break

这样修改后,程序完全按照预想运行了:可以顺利的打印每个线程应该打印的所有数字,也可以中途用Ctrl+C终结整个进程。完整的代码如下:

#!/bin/env python
# -*- coding: utf-8 -*-
#filename: peartest.py

import threading, signal

is_exit = False

def doStress(i, cc):
    global is_exit
    idx = i
    while not is_exit:
        if (idx < 10000000):
            print "thread[%d]: idx=%d"%(i, idx)
            idx = idx + cc
        else:
            break
    if is_exit:
        print "receive a signal to exit, thread[%d] stop."%i
    else:
        print "thread[%d] complete."%i

def handler(signum, frame):
    global is_exit
    is_exit = True
    print "receive a signal %d, is_exit = %d"%(signum, is_exit)

if __name__ == "__main__":
    signal.signal(signal.SIGINT, handler)
    signal.signal(signal.SIGTERM, handler)
    cc = 5
    threads = []
    for i in range(cc):
    t = threading.Thread(target=doStress, args=(i,cc))
    t.setDaemon(True)
    threads.append(t)
    t.start()
    while 1:
        alive = False
        for i in range(cc):
            alive = alive or threads[i].isAlive()
        if not alive:
            break

其实,如果用python写一个服务,也需要这样,因为负责服务的那个线程是永远在那里接收请求的,不会退出,而如果你想用Ctrl+C杀死整个服务,跟上面的压力测试程序是一个道理。

总结一下,python多线程中要响应Ctrl+C的信号以杀死整个进程,需要:

1.把所有子线程设为Daemon;
2.使用isAlive()函数判断所有子线程是否完成,而不是在主线程中用join()函数等待完成;
3.写一个响应Ctrl+C信号的函数,修改全局变量,使得各子线程能够检测到,并正常退出。

Python中用Ctrl+C终止多线程程序的问题解决

Python中用Ctrl+C终止多线程程序的问题解决

复制代码 代码如下:
#!/bin/env python
 # -*- coding: utf-8 -*-
 #filename: peartest.py

 import threading, signal

 is_exit = False

 def doStress(i, cc):
     global is_exit
     idx = i
     while not is_exit:
         if (idx              print "thread[%d]: idx=%d"%(i, idx)
             idx = idx + cc
         else:
             break
     print "thread[%d] complete."%i

 def handler(signum, frame):
     global is_exit
     is_exit = True
     print "receive a signal %d, is_exit = %d"%(signum, is_exit)

 if __name__ == "__main__":
     signal.signal(signal.SIGINT, handler)
     signal.signal(signal.SIGTERM, handler)
     cc = 5
     for i in range(cc):
         t = threading.Thread(target=doStress, args=(i,cc))
         t.start()

上面是一个模拟程序,并不真正向服务发送请求,而代之以在一千万以内,每个线程每隔并发数个(cc个)打印一个整数。很明显,当所有线程都完成自己的任务后,进程会正常退出。但如果我们中途想退出(试想一个压力测试程序,在中途已经发现了问题,需要停止测试),该肿么办?你当然可以用ps查找到进程号,然后kill -9杀掉,但这样太繁琐了,捕捉Ctrl+C是最自然的想法。上面示例程序中已经捕捉了这个信号,并修改全局变量is_exit,线程中会检测这个变量,及时退出。

但事实上这个程序并不work,当你按下Ctrl+C时,程序照常运行,并无任何响应。网上搜了一些资料,明白是python的子线程如果不是daemon的话,主线程是不能响应任何中断的。但设为daemon后主线程会随之退出,接着整个进程很快就退出了,所以还需要在主线程中检测各个子线程的状态,直到所有子线程退出后自己才退出,因此上例29行之后的代码可以修改为:

复制代码 代码如下:
threads=[]
     for i in range(cc):
         t = threading.Thread(target=doStress, args=(i, cc))
         t.setDaemon(True)
         threads.append(t)
         t.start()
     for i in range(cc):
         threads[i].join()

重新试一下,问题依然没有解决,进程还是没有响应Ctrl+C,这是因为join()函数同样会waiting在一个锁上,使主线程无法捕获信号。因此继续修改,调用线程的isAlive()函数判断线程是否完成:

复制代码 代码如下:
while 1:
         alive = False
         for i in range(cc):
             alive = alive or threads[i].isAlive()
         if not alive:
             break

这样修改后,程序完全按照预想运行了:可以顺利的打印每个线程应该打印的所有数字,也可以中途用Ctrl+C终结整个进程。完整的代码如下:

复制代码 代码如下:
#!/bin/env python
 # -*- coding: utf-8 -*-
 #filename: peartest.py

 import threading, signal

 is_exit = False

 def doStress(i, cc):
     global is_exit
     idx = i
     while not is_exit:
         if (idx              print "thread[%d]: idx=%d"%(i, idx)
             idx = idx + cc
         else:
             break
     if is_exit:
         print "receive a signal to exit, thread[%d] stop."%i
     else:
         print "thread[%d] complete."%i

 def handler(signum, frame):
     global is_exit
     is_exit = True
     print "receive a signal %d, is_exit = %d"%(signum, is_exit)

 if __name__ == "__main__":
     signal.signal(signal.SIGINT, handler)
     signal.signal(signal.SIGTERM, handler)
     cc = 5
     threads = []
     for i in range(cc):
         t = threading.Thread(target=doStress, args=(i,cc))
         t.setDaemon(True)
         threads.append(t)
         t.start()
     while 1:
         alive = False
         for i in range(cc):
             alive = alive or threads[i].isAlive()
         if not alive:
             break

其实,如果用python写一个服务,也需要这样,因为负责服务的那个线程是永远在那里接收请求的,不会退出,而如果你想用Ctrl+C杀死整个服务,跟上面的压力测试程序是一个道理。总结一下,python多线程中要响应Ctrl+C的信号以杀死整个进程,需要:

1.把所有子线程设为Daemon;
2.使用isAlive()函数判断所有子线程是否完成,而不是在主线程中用join()函数等待完成;
3.写一个响应Ctrl+C信号的函数,修改全局变量,使得各子线程能够检测到,并正常退出。

Python基础一(认识Python、搭建编程环境、第一个Python程序)

Python基础一(认识Python、搭建编程环境、第一个Python程序)

认识Python

Python的起源

  Python的作者是著名的“龟叔”Guido van Rossum,他希望有一种语言能够像C语言那样,能够全面的调用计算机的功能接口,又能像shell那样,可以轻松的编程。龟叔从ABC语言看到了希望,龟叔也参与到ABC语言的开发,由于一系列原因ABC语言便没有的快速传播使用,因此龟叔开始写Python语言。

Python的诞生

  1989年龟叔为了打发无聊的圣诞节,开始编写Python。1991年Python的第一个编译器诞生,它使用C语言编写的,要能够调用C语言的库文件。

Python的定位

  Python一开始龟叔给他的定位是“优雅、简单、明确”

  Python的官网:Python官网下载

搭建编程环境

  下载地址:Python官网根据自己的版本下载自己的程序

  IDE下载地址:PyCharm下载

  PyCharm的注册码:

CZBSQ81IF5-eyJsaWNlbnNlSWQiOiJDWkJTUTgxSUY1IiwibGljZW5zZWVOYW1lIjoiTGl0dGxlIGZlaSIsImFzc2lnbmVlTmFtZSI6IiIsImFzc2lnbmVlRW1haWwiOiIiLCJsaWNlbnNlUmVzdHJpY3Rpb24iOiJGb3IgZWR1Y2F0aW9uYWwgdXNlIG9ubHkiLCJjaGVja0NvbmN1cnJlbnRVc2UiOmZhbHNlLCJwcm9kdWN0cyI6W3siY29kZSI6IklJIiwicGFpZFVwVG8iOiIyMDE5LTAxLTMwIn0seyJjb2RlIjoiUlMwIiwicGFpZFVwVG8iOiIyMDE5LTAxLTMwIn0seyJjb2RlIjoiV1MiLCJwYWlkVXBUbyI6IjIwMTktMDEtMzAifSx7ImNvZGUiOiJSRCIsInBhaWRVcFRvIjoiMjAxOS0wMS0zMCJ9LHsiY29kZSI6IlJDIiwicGFpZFVwVG8iOiIyMDE5LTAxLTMwIn0seyJjb2RlIjoiREMiLCJwYWlkVXBUbyI6IjIwMTktMDEtMzAifSx7ImNvZGUiOiJEQiIsInBhaWRVcFRvIjoiMjAxOS0wMS0zMCJ9LHsiY29kZSI6IlJNIiwicGFpZFVwVG8iOiIyMDE5LTAxLTMwIn0seyJjb2RlIjoiRE0iLCJwYWlkVXBUbyI6IjIwMTktMDEtMzAifSx7ImNvZGUiOiJBQyIsInBhaWRVcFRvIjoiMjAxOS0wMS0zMCJ9LHsiY29kZSI6IkRQTiIsInBhaWRVcFRvIjoiMjAxOS0wMS0zMCJ9LHsiY29kZSI6IkdPIiwicGFpZFVwVG8iOiIyMDE5LTAxLTMwIn0seyJjb2RlIjoiUFMiLCJwYWlkVXBUbyI6IjIwMTktMDEtMzAifSx7ImNvZGUiOiJDTCIsInBhaWRVcFRvIjoiMjAxOS0wMS0zMCJ9LHsiY29kZSI6IlBDIiwicGFpZFVwVG8iOiIyMDE5LTAxLTMwIn0seyJjb2RlIjoiUlNVIiwicGFpZFVwVG8iOiIyMDE5LTAxLTMwIn1dLCJoYXNoIjoiNzkzODk3Mi8wIiwiZ3JhY2VQZXJpb2REYXlzIjowLCJhdXRvUHJvbG9uZ2F0ZWQiOmZhbHNlLCJpc0F1dG9Qcm9sb25nYXRlZCI6ZmFsc2V9-kEgxAjNsTpESbd6SeKvDNbifpcDEL9X+7s+KuaEj6PubI6HWadsgH0mlgxx9JTQ+LM72dFDQIddju3EBjOOA8GiPAUyb/bSObgXDxbSD+xnqFM/9zcB47WU218RwToZEWjeCbXcM4TmIlznHaUNQWFbwYgAjY1iuuRkk5pAt87RQ2QqDBLXPXjQR6ytxvz5rS9cmryka0zenevU8C8u1C37mbCKYaFAqHxY1z+rDSU/MuVz9bplIZ/soskVeabPppcZsixf+W5LonqQQ9CUaaIjH4KsWtfAxSJMzoQ5A0EplLRT7HZkez4V2UMylNfg8PtgwE96LEUqKdp4VjzDVQA==-MIIEPjCCAiagAwIBAgIBBTANBgkqhkiG9w0BAQsFADAYMRYwFAYDVQQDDA1KZXRQcm9maWxlIENBMB4XDTE1MTEwMjA4MjE0OFoXDTE4MTEwMTA4MjE0OFowETEPMA0GA1UEAwwGcHJvZDN5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxcQkq+zdxlR2mmRYBPzGbUNdMN6OaXiXzxIWtMEkrJMO/5oUfQJbLLuMSMK0QHFmaI37WShyxZcfRCidwXjot4zmNBKnlyHodDij/78TmVqFl8nOeD5+07B8VEaIu7c3E1N+e1doC6wht4I4+IEmtsPAdoaj5WCQVQbrI8KeT8M9VcBIWX7fD0fhexfg3ZRt0xqwMcXGNp3DdJHiO0rCdU+Itv7EmtnSVq9jBG1usMSFvMowR25mju2JcPFp1+I4ZI+FqgR8gyG8oiNDyNEoAbsR3lOpI7grUYSvkB/xVy/VoklPCK2h0f0GJxFjnye8NT1PAywoyl7RmiAVRE/EKwIDAQABo4GZMIGWMAkGA1UdEwQCMAAwHQYDVR0OBBYEFGEpG9oZGcfLMGNBkY7SgHiMGgTcMEgGA1UdIwRBMD+AFKOetkhnQhI2Qb1t4Lm0oFKLl/GzoRykGjAYMRYwFAYDVQQDDA1KZXRQcm9maWxlIENBggkA0myxg7KDeeEwEwYDVR0lBAwwCgYIKwYBBQUHAwEwCwYDVR0PBAQDAgWgMA0GCSqGSIb3DQEBCwUAA4ICAQC9WZuYgQedSuOc5TOUSrRigMw4/+wuC5EtZBfvdl4HT/8vzMW/oUlIP4YCvA0XKyBaCJ2iX+ZCDKoPfiYXiaSiH+HxAPV6J79vvouxKrWg2XV6ShFtPLP+0gPdGq3x9R3+kJbmAm8w+FOdlWqAfJrLvpzMGNeDU14YGXiZ9bVzmIQbwrBA+c/F4tlK/DV07dsNExihqFoibnqDiVNTGombaU2dDup2gwKdL81ua8EIcGNExHe82kjF4zwfadHk3bQVvbfdAwxcDy4xBjs3L4raPLU3yenSzr/OEur1+jfOxnQSmEcMXKXgrAQ9U55gwjcOFKrgOxEdek/Sk1VfOjvS+nuM4eyEruFMfaZHzoQiuw4IqgGc45ohFH0UUyjYcuFxxDSU9lMCv8qdHKm+wnPRb0l9l5vXsCBDuhAGYD6ss+Ga+aDY6f/qXZuUCEUOH3QUNbbCUlviSz6+GiRnt1kA9N2Qachl+2yBfaqUqr8h7Z2gsx5LcIf5kYNsqJ0GavXTVyWh7PYiKX4bs354ZQLUwwa/cG++2+wNWP+HtBhVxMRNTdVhSm38AknZlD+PTAsWGu9GyLmhti2EnVwGybSD2Dxmhxk3IPCkhKAK+pl0eWYGZWG3tJ9mZ7SowcXLWDFAk0lRJnKGFMTggrWjV8GYpw5bq23VmIqqDLgkNzuoog==

 Python第一个程序

print("hello Python")

思考题:

编写一段程序输出自己的姓名和年龄(使用变量)

name = input("请输入您的姓名:")
age = input("请输入您的年龄:")
print("您的姓名是:",name,"您的年龄是:",age)

 

关于终止多线程python程序python停止多线程的问题我们已经讲解完毕,感谢您的阅读,如果还想了解更多关于Linux下后台运行和终止python程序常用命令、Python 中用 Ctrl+C 终止多线程程序的问题解决、Python中用Ctrl+C终止多线程程序的问题解决、Python基础一(认识Python、搭建编程环境、第一个Python程序)等相关内容,可以在本站寻找。

本文标签:

上一篇Python:使用索引作为值将列表转换为字典(python以列表为索引的列表)

下一篇Consul 的开发者模式之 Docker 版(开发docker教程)