我怎么猴子补丁lxml?

时间:2014-08-12 23:22:27

标签: python lxml gevent

我正在使用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会阻塞。

1 个答案:

答案 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套接字模块。您最好的选择是按计划进行,从解析操作中执行带外检索。