代码之家  ›  专栏  ›  技术社区  ›  user_78361084

我如何修补lxml?

  •  1
  • user_78361084  · 技术社区  · 10 年前

    我正在使用gevent处理一些url;其中一些我使用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 回复  |  直到 10 年前
        1
  •  2
  •   Charles Duffy    10 年前

    gevent.monkey 如文件所述 Python标准库 与gevent的模型合作。

    lxml不是标准库的一部分;因此,它不受 gevent.monkey .

    的确,如果你看看 the module documentation ,您将找到它知道如何修补的目标模块列表; socket 是集合的成员; lxml 当然不是。


    因此,对于更大的问题——“我如何为gevent支持修补lxml?”的答案是“首先,编写支持gevent模型的底层调用的实现”。

    然而,由于lxml植根于C而不是停留在Python中,这甚至不一定是可能的,除非接口以可访问的方式明确抽象——而且lxml的open()调用没有受到猴子修补套接字模块的影响,这清楚地表明(例如,与请求模块不同)它使用的是libxml2的本机功能,而不是Python套接字模块。最好的办法是按计划进行,从解析操作中执行带外检索。