requests.get 挂起的多处理
Multiprocessing hanging with requests.get
我一直在使用一段非常简单的代码,但行为却很奇怪。我正在尝试使用 requests.get
向网页发送请求,但如果请求花费的时间超过几秒钟,我想终止该进程。我正在关注接受的答案 here 的响应,但更改函数体以包含 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')
上面的代码在 运行ning 时简单地挂起。然而,当我 运行
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
有关。这怎么可能?我发现了一个类似的问题 here,但我没有使用 async
。问题是否与猴子补丁有关,因为我正在使用 requests
以及 time
和 multiprocessing
?任何建议或意见将不胜感激。谢谢!
我正在使用:
Python 3.7.0
requests
2.21.0
编辑:@Hitobat 指出参数 timeout
可以代替 requests
使用。这确实有效,但是,对于 requests
为什么 multiprocessing
.
失败的任何其他想法,我将不胜感激
我已经重现了你的场景,我不得不反驳上述假设"I am certain the behavior has to do with requests"。
requests.get(...)
returns 响应符合预期。
让我们看看这个过程如何进行一些调试:
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
块语句,但它 hangs/stops 在语句 q.get()
试图从队列中提取数据时。
因此我们可以得出结论,队列很可能已损坏。
我们在 multiprocessing
库文档(Pipes and Queues
部分)中有相应的警告:
Warning
If a process is killed using Process.terminate()
or os.kill() while
it is trying to use a Queue, then the data in the queue is likely to
become corrupted. This may cause any other process to get an exception
when it tries to use the queue later on.
看来是这种情况。
我们如何处理这个问题?
已知的解决方法是使用 mp.Manager().Queue()
(具有中间 代理 级别)而不是 mp.Queue
:
...
q = mp.Manager().Queue()
p = mp.Process(target=get_page, args=(q,))
我一直在使用一段非常简单的代码,但行为却很奇怪。我正在尝试使用 requests.get
向网页发送请求,但如果请求花费的时间超过几秒钟,我想终止该进程。我正在关注接受的答案 here 的响应,但更改函数体以包含 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')
上面的代码在 运行ning 时简单地挂起。然而,当我 运行
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
有关。这怎么可能?我发现了一个类似的问题 here,但我没有使用 async
。问题是否与猴子补丁有关,因为我正在使用 requests
以及 time
和 multiprocessing
?任何建议或意见将不胜感激。谢谢!
我正在使用:
Python 3.7.0
requests
2.21.0
编辑:@Hitobat 指出参数 timeout
可以代替 requests
使用。这确实有效,但是,对于 requests
为什么 multiprocessing
.
我已经重现了你的场景,我不得不反驳上述假设"I am certain the behavior has to do with requests"。
requests.get(...)
returns 响应符合预期。
让我们看看这个过程如何进行一些调试:
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
块语句,但它 hangs/stops 在语句 q.get()
试图从队列中提取数据时。
因此我们可以得出结论,队列很可能已损坏。
我们在 multiprocessing
库文档(Pipes and Queues
部分)中有相应的警告:
Warning
If a process is killed using
Process.terminate()
or os.kill() while it is trying to use a Queue, then the data in the queue is likely to become corrupted. This may cause any other process to get an exception when it tries to use the queue later on.
看来是这种情况。
我们如何处理这个问题?
已知的解决方法是使用 mp.Manager().Queue()
(具有中间 代理 级别)而不是 mp.Queue
:
...
q = mp.Manager().Queue()
p = mp.Process(target=get_page, args=(q,))