中止HTTP请求交叉线程

2024-06-26 17:59:50 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在从C移植我的一个项目,在Python中解决多线程问题时遇到了困难。该问题与预期的长生存期HTTP请求有关(当服务器上发生某个事件时,该请求将响应)。总结如下:

我在一个单独的线程上使用urllib2发送请求。当请求返回或超时时,将通知主线程。这个很好用。但是,在某些情况下,我需要中止这个未完成的请求并切换到另一个URL。我可以考虑四种解决方案:

  1. 中止未完成的请求。C有WebRequest.Abort(),我可以调用它来中止请求。Pythonurllib2.Request似乎是一个纯数据类,在这种情况下,只存储请求信息;响应不连接到请求对象。所以我不能这么做。在
  2. 中断线程。C有Thread.Interrupt(),如果线程处于等待状态,或者下次进入这种状态时,它将在线程中引发一个{}。(等待监视器和文件/套接字I/O都是等待状态)Python似乎没有任何可比性;似乎没有一种方法可以唤醒I/O阻塞的线程
  3. 设置请求的低超时。超时时,检查“中止”标志。如果为false,请重新启动请求。在
  4. 与选项3类似,向state对象添加一个“aborted”标志,以便当请求最终以某种方式结束时,线程知道不再需要响应,而只关闭自己。在

选项3和选项4似乎是Python支持的唯一选项,但选项3是一个糟糕的解决方案,4将保持打开一个我不需要的连接。我希望成为一个好的网民,当我不再需要它的时候关闭这个连接。是否有任何方法可以实际中止未完成的请求,以某种方式?在


Tags: 项目对象方法服务器http标志状态选项
3条回答

与斯派克·格罗尼姆的回答相似,但更为严厉。在

考虑用twisted重写这个。您可能希望子类twisted.web.http.HTTPClient,特别是实现handleResponsePart来进行客户机交互(或者{},如果您不需要在响应结束之前看到它)。要尽早关闭连接,只需调用客户端协议上的loseConnection方法。在

考虑使用gevent。Gevent使用称为greenlets的非线程协作执行单元。Greenlets可以“阻止”IO,这实际上意味着“在IO准备好之前睡觉”。您可以有一个拥有套接字的请求者greenlet和一个决定何时中止的主greenlet。当您想中止和切换url时,主greenlet会杀死请求者greenlet。请求程序捕获结果异常,关闭其socket/urllib2请求,然后重新开始。在

编辑后添加:Gevent与线程不兼容,因此要小心。您必须一直使用gevent或线程。由于GIL,python中的线程有点蹩脚。在

如果你别无选择,也许“可杀死线程”的this snippet可能对你有用。但我的观点与Spike Gronim相同,并建议使用gevent。在

相关问题 更多 >