终止长时间运行的python线程

时间:2009-08-04 07:25:14

标签: python multithreading

在python中终止意外长时间运行的线程的推荐方法是什么?我不能使用SIGALRM,因为

  

如果两者都必须小心   信号和线程用于   同样的计划。根本要做的事情   记住使用信号和线程   同时是:始终执行   主线程中的signal()操作   执行。任何线程都可以执行   一个alarm(),getsignal(),pause(),   setitimer()或getitimer(); 只有   主线程可以设置新信号   处理程序,主线程将是   唯一一个接收信号的人   (这是由Python信号强制执行的   模块,即使是底层线程   实现支持发送   向各个线程发出信号)。这个   意味着信号不能用作   线程间的手段   communication.Use lock。

更新:我的案例块中的每个线程 - 它正在使用urllib2模块下载网页,有时操作在极慢的网站上花费太多时间。这就是我想终止这种慢线程的原因

4 个答案:

答案 0 :(得分:6)

由于突然杀死阻塞调用中的线程是不可行的,因此在可能的情况下,更好的方法是避免使用线程来支持不受此类问题影响的其他多任务机制。

对于OP的具体情况(线程的工作是下载网页,有些线程由于行为不当的网站而永远阻塞),理想的解决方案是twisted - 因为它通常用于网络任务。在其他情况下,multiprocessing可能会更好。

更一般地说,当线程提出无法解决的问题时,我建议切换到其他多任务处理机制,而不是尝试使用线程执行任务的英雄措施,至少在CPython中,它们是不适合的。

答案 1 :(得分:5)

正如Alex Martelli建议的那样,您可以使用多处理模块。它与Threading模块非常相似,因此可以让您轻松上手。您的代码可以是这样的,例如:

import multiprocessing

def get_page(*args, **kwargs):
    # your web page downloading code goes here

def start_get_page(timeout, *args, **kwargs):
    p = multiprocessing.Process(target=get_page, args=args, kwargs=kwargs)
    p.start()
    p.join(timeout)
    if p.is_alive():
        # stop the downloading 'thread'
        p.terminate()
        # and then do any post-error processing here

if __name__ == "__main__":
    start_get_page(timeout, *args, **kwargs)

当然,您需要以某种方式获取页面下载代码的返回值。为此,您可以使用多处理。管道或多处理.Queue(或多处理可用的其他方式)。有更多信息,以及您可以在http://docs.python.org/library/multiprocessing.html查看的样本。

最后,多处理模块包含在python 2.6中。它也适用于pypi的python 2.5和2.4(你可以使用

  

easy_install多处理

或者只是访问pypi并手动下载并安装软件包。

注意:我意识到这已经发布了一段时间。我遇到了类似的问题,偶然发现了Alex Martelli的建议。如果它实现了我的问题,并决定分享它。 (我要感谢Alex指出我正确的方向。)

答案 2 :(得分:1)

如果您试图杀死一个您无法控制其代码的线程,则取决于该线程是否处于阻塞调用中。根据我的经验,如果线程正确阻塞,则没有推荐和可移植的方法。

当我尝试使用标准库中的代码(multiprocessing.manager我正在看着你)时,我遇到了这种情况,循环编码没有退出条件:很好!

有一些可插入的线程实现(see here for an example),但是,如果您自己控制了线程代码,那么您应该能够以一种可以用它们来中断它们的方式来编写它们。某种条件变量。

答案 3 :(得分:1)

使用同步对象并要求线程终止。基本上,写这个合作处理。

如果你开始把python解释器下面的线程拉出来,可能会发生各种奇怪的事情,而且它也不只是在Python中,大多数运行时都有这个问题。

例如,假设您在打开文件后杀死了一个线程,在该应用程序终止之前,该文件无法关闭。