Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/300.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
python中解析(流)XML的非阻塞方法_Python_Xml_Parsing_Nonblocking - Fatal编程技术网

python中解析(流)XML的非阻塞方法

python中解析(流)XML的非阻塞方法,python,xml,parsing,nonblocking,Python,Xml,Parsing,Nonblocking,我有一个XML文档通过一个套接字传入,我需要动态解析和响应它(即解析部分树)。我想要的是这样做的非阻塞方法,这样我就可以在等待更多数据进入时做其他事情(无需线程) 如果在读取缓冲区为空时完成迭代,则类似于iterparse的内容将非常理想,例如: context = iterparse(imaginary_socket_file_wrapper) while 1: for event, elem in context: process_elem(elem) # i

我有一个XML文档通过一个套接字传入,我需要动态解析和响应它(即解析部分树)。我想要的是这样做的非阻塞方法,这样我就可以在等待更多数据进入时做其他事情(无需线程)

如果在读取缓冲区为空时完成迭代,则类似于iterparse的内容将非常理想,例如:

context = iterparse(imaginary_socket_file_wrapper)
while 1:
    for event, elem in context:
        process_elem(elem)
    # iteration of context finishes when socket has no more data
    do_other_stuff()
    time.sleep(0.1)
我想SAX也是一种选择,但iterparse似乎更适合我的需要。有什么想法吗

更新:


使用线程是很好的,但引入了我希望避开的复杂性级别。我认为非阻塞调用是一种很好的方法,但我发现它增加了解析XML的复杂性。

如果不使用线程,可以使用事件循环并轮询非阻塞套接字

是这类东西的标准库模块。是Python的异步库,但很复杂,可能有点重,适合您的需要

或者,是非线程线程的替代方案,但我假设您没有运行2.6


无论如何,我认为您必须使用线程、额外的进程或编织一些同样复杂的异步魔法。

我认为这有两个组件,非阻塞网络I/O和面向流的XML解析器

对于前者,您必须选择一个非阻塞网络框架,或者为此推出您自己的解决方案。Twisted当然会起作用,但我个人觉得控制框架的反转很难让我的大脑思考。您可能需要跟踪回调中的许多状态,以向解析器提供反馈。出于这个原因,我倾向于找到一个更容易编程的方法,我认为它非常适合这种情况

本质上,它允许您编写代码,就像使用阻塞套接字调用一样(使用普通循环或生成器或任何您喜欢的方法),但您可以将其生成一个单独的协程(“greenlet”),当I/O操作阻塞时,该协程将自动执行协作产出,从而允许其他协同程序运行

这使得使用任何面向流的解析器再次变得微不足道,因为代码的结构类似于普通的阻塞调用。这还意味着许多不直接处理套接字或其他I/O(例如解析器)的库不必经过特殊修改而成为非阻塞库:如果它们阻塞,Eventlet将生成协同路由


诚然,Eventlet有点神奇,但我发现它的学习曲线比Twisted简单得多,并且生成的代码更简单,因为您不必将逻辑“由内而外”以适应框架。

深入到iterparse源代码为我提供了解决方案。下面是一个简单的示例,演示如何动态构建XML树并在元素的关闭标记后处理元素:

import xml.etree.ElementTree as etree

parser = etree.XMLTreeBuilder()

def end_tag_event(tag):
    node = self.parser._end(tag)
    print node

parser._parser.EndElementHandler = end_tag_event

def data_received(data):
    parser.feed(data)

在我的例子中,我最终从twisted向它提供了数据,但它也应该能够与非阻塞套接字一起工作。

twisted确实很难让你动脑,尽管一旦你理解了
延迟的
s,它的功能就非常强大。我简要介绍了eventlet,它基于线程,OP排除了这一点。但没有说明为什么线程不是一个选项。如果这是一个复杂的问题,Eventlet看起来充满了win。实际上,Eventlet不需要线程,但它与线程正交并兼容。它使用了一个名为“greenlet”的C扩展,它实现了协作协程,这可以被认为是Python生成器的一个通用版本:greenlet可以产生控制权,并在稍后恢复到它停止的地方。Eventlet使用此功能在执行将阻塞的I/O操作时自动生成任何greenlet,然后在I/O完成时恢复该操作。事实上,它在引擎盖下使用了一个类似于Twisted的反应器,但是为了调度greenlets而不是直接暴露它。Twisted似乎专注于HTML和HTTP。有没有将Twisted与普通的ol'XML和TCP套接字一起使用的例子?edarc:哦,对了,明白了。与使用线程相比,它有什么优势?greenlet比操作系统线程轻得多。把它们想象成Erlang进程——它们是虚拟机的产物,而不是具有伴随内存和上下文切换开销的真实OS线程。因此,通过线程模型的直接控制流,您可以获得非阻塞事件驱动模型的并发性优势。asyncore看起来不错,但我仍然需要一种解析XML的方法,这种方法不会超过将iterparse放入另一个线程(比如)的复杂性。我不知道为什么线程被删除了。Eventlet看起来不错,但在本例中并不比线程简单。在我看来,如果您想要并发/异步/线程化的行为,您必须以某种方式为这种复杂性付出代价。XML库(或几乎任何其他库)不会附带这种功能,因为它在不同的抽象级别上做得更好。多亏了你的回答,我终于找到了我问题的另一个答案。请看我更详细的回答: