我正在使用gevent处理一些网址;其中一些我使用lxml的etree来检索&解析回复。当我使用etree.parse(url)
检索这些网址时,它似乎是阻塞的,即使我已经修补了所有内容。如果我通过请求检索,则不会发生阻塞。
import time
import gevent
from lxml import etree
from gevent import monkey
monkey.patch_all()
import requests
def first():
url = 'http://www.google.com'
r = requests.get(url)
return r
def second():
url = 'http://url_to_large_xml_that_requires_api_key'
r = etree.parse(url) # this blocks "first()"
#r = requests.get(url)
return r
def get_external(i):
if i == 'first':
return first()
elif i == 'second':
return second()
threads = [gevent.spawn(get_external, i) for i in ['first', 'second']]
gevent.joinall(threads)
如果我取消注释r = requests.get(url)
并注释掉r = etree.parse(url)
,则整个脚本运行得更快,并且不会阻止first
。我知道一个解决方案可能是获取请求&然后通过etree处理,但我想先了解为什么etree会阻塞。
答案 0 :(得分:2)
gevent.monkey
使 Python标准库与gevent的模型合作。
lxml不是标准库的一部分;因此,gevent.monkey
不支持它也就不足为奇了。
的确,如果你看一下the module documentation,你会发现一个目标模块列表,它知道如何修补; socket
是该集合的成员; lxml
当然不是。
所以,对于一个更大的问题 - 答案是"我如何使用补丁lxml进行gevent支持?"以&#34开头;首先,编写支持gevent模型的基础调用的实现"。
然而,由于lxml植根于C而不是留在Python中,除非界面明显以可访问的方式抽象,否则这种情况不一定是可能的 - 并且lxml的open()调用不是&通过猴子修补实现套接字模块是一个明确的指示器(不像,例如,请求模块),它使用libxml2的本机功能而不是Python套接字模块。您最好的选择是按计划进行,从解析操作中执行带外检索。