终止长时间运行的python线程

Kon*_*tin 5 python multithreading

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

如果在同一程序中使用信号和线程,则必须小心.在同时使用信号和线程时要记住的基本要点是:始终在执行的主线程中执行signal()操作.任何线程都可以执行alarm(),getsignal(),pause(),setitimer()或getitimer(); 只有主线程可以设置一个新的信号处理程序,主线程将是唯一一个接收信号的线程 (这是由Python信号模块强制执行的,即使底层线程实现支持向各个线程发送信号).这意味着信号不能用作线程间通信的手段.请使用锁定.

更新:我的案例块中的每个线程 - 它正在使用urllib2模块下载网页,有时在非常慢的站点上操作需要太多时间.这就是为什么我想终止这么慢的线程

Ale*_*lli 6

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

对于OP的特定情况(线程的工作是下载网页,并且一些线程由于行为不当的网站而永远阻塞),理想的解决方案是扭曲的 - 因为它通常用于网络任务.在其他情况下,多处理可能更好.

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


Vin*_*n-G 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)
Run Code Online (Sandbox Code Playgroud)

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

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

easy_install多处理

)

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

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