多处理挂起与请求.get



我一直在使用一些非常简单的代码,但行为非常奇怪。我正在尝试使用requests.get向网页发送请求,但如果请求时间超过几秒钟,我想终止该过程。我在这里遵循已接受答案的响应,但更改函数体以包含request.我的代码如下:

import multiprocessing as mp, requests
def get_page(_r):                   
_rs = requests.get('https://www.woolworths.com.au/shop/browse/drinks/cordials-juices-iced-teas/iced-teas').text
_r.put(_rs)
q = mp.Queue() 
p = mp.Process(target=get_page, args=(q,))
p.start()
time.sleep(3)
p.terminate()
p.join()
try:
result = q.get(False)
print(result)
except:
print('failed')

上面的代码在运行时只是挂起。但是,当我跑步时

requests.get('https://www.woolworths.com.au/shop/browse/drinks/cordials-juices-iced-teas/iced-teas').text

独立地,响应将在两秒内返回。因此,主代码应该打印页面的 HTML,但是,它只是停滞不前。奇怪的是,当我在get_page中放置一个无限循环时:

def get_page(_r): 
while True:
pass
_r.put('You will not see this')

该过程确实在三秒钟后终止。因此,我确信这种行为与requests有关。这怎么可能?我在这里发现了一个类似的问题,但我没有使用async.这个问题是否与猴子补丁有关,因为我正在使用requests以及timemultiprocessing?任何建议或意见将不胜感激。谢谢!

我正在使用:

  • 蟒蛇 3.7.0

  • requests2.21.0

编辑:@Hitobat指出,参数timeout可以与requests一起使用。这确实有效,但是,我将不胜感激有关requestsmultiprocessing而失败的任何其他想法。

我已经重现了您的场景,我必须反驳提到的假设"我确信该行为与请求有关"。
requests.get(...)按预期返回响应。

让我们看看这个过程是如何进行的,有一些调试点:

import multiprocessing as mp, requests
import time

def get_page(_r):
_rs = requests.get('https://www.woolworths.com.au/shop/browse/drinks/cordials-juices-iced-teas/iced-teas').text
print('--- response header', _rs[:17])
_r.put(_rs)

q = mp.Queue()
p = mp.Process(target=get_page, args=(q,))
p.start()
time.sleep(3)
p.terminate()
p.join()
try:
print('--- get data from queue of size', q.qsize())
result = q.get(False)
print(result)
except Exception as ex:
print('failed', str(ex))

输出:

--- response header 
<!DOCTYPE html>
--- get data from queue of size 1

正如我们所看到的,响应就在那里,该过程甚至前进到try块语句,但是当尝试从队列中提取数据时,它会挂起/停止在语句q.get()。 因此,我们可以得出结论,队列可能已损坏。 我们在multiprocessing库文档中有相应的警告(Pipes and Queues部分(:

警告

如果使用Process.terminate()或 os.kill(( 杀死进程,则 它正在尝试使用队列,那么队列中的数据可能会 变得腐败。这可能会导致任何其他进程出现异常 当它稍后尝试使用队列时。

看起来就是这种情况。


我们如何处理这个问题?

一个已知的解决方法是使用mp.Manager().Queue()(具有中间代理级别(而不是mp.Queue

...
q = mp.Manager().Queue()
p = mp.Process(target=get_page, args=(q,))

相关内容

  • 没有找到相关文章

最新更新