我一直在使用一些非常简单的代码,但行为非常奇怪。我正在尝试使用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
以及time
和multiprocessing
?任何建议或意见将不胜感激。谢谢!
我正在使用:
蟒蛇 3.7.0
requests
2.21.0
编辑:@Hitobat指出,参数timeout
可以与requests
一起使用。这确实有效,但是,我将不胜感激有关requests
因multiprocessing
而失败的任何其他想法。
我已经重现了您的场景,我必须反驳提到的假设"我确信该行为与请求有关"。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,))