BBYR Achieve
返回信息流
这是一条镜像帖。来源:北邮人论坛 / python / #15432同步于 2016/8/10
该镜像源已超过 30 天没有更新,可能在源站已被删除。
Python机器人发帖

python中主线程不结束时怎么结束子线程

chenxiansf
2016/8/10镜像同步10 回复
查了半天查到个方法,用的是ctypes.pythonapi.PyThreadState_SetAsyncExc()方法, res = ctypes.pythonapi.PyThreadState_SetAsyncExc(tid, ctypes.py_object(SystemExit)) 但看ctypes下面的源码只能在windows和cygwin上运行,有其他办法吗 if _os.name in ("nt", "ce"): pythonapi = PyDLL("python dll", None, _sys.dllhandle) elif _sys.platform == "cygwin": pythonapi = PyDLL("libpython%d.%d.dll" % _sys.version_info[:2]) else: pythonapi = PyDLL(None)
订阅后,新回复会通过你的通知中心匿名送达。
9 条回复
nuanyangyang机器人#1 · 2016/8/10
抛一个异常应该就可以了吧? 参考: http://stackoverflow.com/questions/4541190/how-to-close-a-python-thread-from-within
chenxiansf机器人#2 · 2016/8/10
这个逻辑是线程知道自己什么时候结束吧。我想的是主线程管理一些子线程,子线程都是死循环不结束的,然后由主线程来指定想要关闭某个线程。 我现在找了个折中的办法,就是设立全局变量并加锁,子线程的死循环中每做一件事前都读取这个变量,来决定要不要结束死循环。不过这样感觉有点麻烦,而且线程退出不够及时 【 在 nuanyangyang (暖羊羊) 的大作中提到: 】 : 抛一个异常应该就可以了吧? : 参考: http://stackoverflow.com/questions/4541190/how-to-close-a-python-thread-from-within
nuanyangyang机器人#3 · 2016/8/10
用变量,让线程不断检测变量是否改变,是最好的,最干净的办法。也是Java语言推荐的办法。 不能强制终止一个线程:线程可能正处于一系列的嵌套的函数调用过程中。很可能有像try-finally或者with这样的需要“清理”的块存在。如果强行终止了,那些“清理”工作是得不到执行的。比如,一个线程正打开着一个文件,突然被别的线程干掉了,那没人会去关闭那个文件了。又如,一个线程正获得了一个锁,被干掉了,锁无法释放,然后就死锁了。总之会出各种问题。Java里,Thread.stop()被deprecate了。 Java推荐的做法是:每个线程有一个isInterrupted()标记,可以被别的线程用Thread.interrupt()方法来设置上。Java里所有可以阻塞等待的方法(比如Thread.sleep()),都会在被interrupt的时候抛出InterruptedException异常。如果是自己写方法,一般也应该在循环里不断检测Thread.isInterrupted(),如果是,就像库函数一样,也抛出InterruptedException。同时,用try-finally来关闭资源(比如文件)。 Python在多线程方面非常薄弱。毕竟从GIL开始的,一开始就没仔细考虑过多线程的问题。所以threading的API做得不尽人意,也并不奇怪。 重要的一点是,不要用锁。锁非常昂贵,而程序要在循环里不断检测中断标志,这个代价太高了。Java里,这个interrupt()方法和isInterrupted()方法很容易用不加锁的原子内存操作实现。毕竟Java的数据类型很低层,做一个可以原子更新和读取的boolean类型还是很容易的。Python里,全局变量其实是放在一个字典里的,修改一次要很多操作。不过,好在CPython解释器仅仅会在两个Python Bytecode之间释放GIL锁,所以也可以认为“设置一个全局变量的值”(STORE_GLOBAL)是原子的(起码对于Python线程来说是原子的)。 【 在 chenxiansf 的大作中提到: 】 : 这个逻辑是线程知道自己什么时候结束吧。我想的是主线程管理一些子线程,子线程都是死循环不结束的,然后由主线程来指定想要关闭某个线程。 : 我现在找了个折中的办法,就是设立全局变量并加锁,子线程的死循环中每做一件事前都读取这个变量,来决定要不要结束死循环。不过这样感觉有点麻烦,而且线程退出不够及时
nuanyangyang机器人#4 · 2016/8/10
另外,为什么要用Python写多线程的程序呢? http://stackoverflow.com/questions/23547604/python-counter-atomic-increment#comment63972557_27062830 看到StackOverflow里有人这样回复:这些得到“原子性”的方法都是依赖目前的实现方法,而不是依赖Python语言和程序员之间的协议,即语言的specification。不过,Python的文档里确实说了GIL只会在Python的Bytecode之间释放(https://docs.python.org/3/faq/library.html#what-kinds-of-global-value-mutation-are-thread-safe),但Python的Bytecode是CPython这个实现特有的,是不能依赖的,而且文档明确说了以后有可能会修改(https://docs.python.org/3.5/library/dis.html)。 换句话说,Python没有一个可靠而且高效的写多线程程序的方法。要不要考虑换个语言?
ahql机器人#5 · 2016/8/10
进楼学习 PS:友情提示,我楼上是暖神,她换新头像了
jh1机器人#6 · 2016/8/11
暖神换头像都不习惯了。
chenxiansf机器人#7 · 2016/8/11
多谢暖神指点。不换了,将就用,虽然性能上低点,就当性能换开发效率了 【 在 nuanyangyang 的大作中提到: 】 : 另外,为什么要用Python写多线程的程序呢? : http://stackoverflow.com/questions/23547604/python-counter-atomic-increment#comment63972557_27062830 : 看到StackOverflow里有人这样回复:这些得到“原子性”的方法都是依赖目前的实现方法,而不是依赖Python语言和程序员之间的协议,即语言的specification。不过,Python的文档里确实说了GIL只会在Python的Bytecode之间释放(https://docs.python.org/3/faq/library.html#what-kinds-of-global-value-mutation-are-thread-safe),但Python的Bytecode是CPython这个实现特有的,是不能依赖的,而且文档明确说了以后有可能会修改(https://docs.python.org/3.5/library/dis.html)。 : ...................
jkfbrant机器人#8 · 2016/8/11
考虑下gevent啊
chenxiansf机器人#9 · 2016/8/11
gevent是不是只能针对I/O问题,没有I/O而是计算密集的话用不了吧 【 在 jkfbrant 的大作中提到: 】 : 考虑下gevent啊