事件驅動解析

2021-10-22 07:49:30 字數 3434 閱讀 8053

有時我們需要的只是樹內某個地方的一小部分,因此將整個樹解析到記憶體中,全體遍歷並進行相關操作造成的記憶體開銷會很大

因此,etree提供了兩個事件驅動的解析器介面

乙個是在構建樹時,生成解析器事件(iterparse)

另乙個根本不構建樹,而是以類似sax的方式呼叫目標物件的反饋方法

some_file_like = bytesio(b"data

")for event, element in etree.iterparse(some_file_like):

print("%s, %4s, %s" % (event, element.tag, element.text)

'''輸出:

end, a, data

end, root, none

'''

預設情況下,iterparse()只在解析完元素時生成事件,但可以通過events關鍵字引數控制

some_file_like = bytesio(b"data

")for event, element in etree.iterparse(some_file_like,events=("start", "end")):

print("%5s, %4s, %s" % (event, element.tag, element.text))

'''輸出:

start, root, none

start, a, data

end, a, data

end, root, none

'''

注意,在接收開始事件時,元素的文字、尾部和子元素還不一定存在,只有結束事件才能保證元素已被完全解析

它還允許您.clear()或修改元素的內容以節省記憶體

因此,如果您解析乙個大的樹並且希望保持記憶體使用量小,那麼您應該清理樹中不再需要的部分

.clear()的keep_tail=true引數確保當前元素後面的(tail)文字內容不會被觸控

強烈建議修改解析器可能尚未完全讀取的任何內容

some_file_like = bytesio(b"data")

for event, element in etree.iterparse(some_file_like):

if element.tag == 'b':

print(element.text)

elif element.tag == 'a':

print("** cleaning up the subtree")

element.clear(keep_tail=true)

'''輸出:

data

** cleaning up the subtree

none

** cleaning up the subtree

'''

iterparse()的乙個非常重要的用例是解析生成的大型xml檔案,例如資料庫轉儲

大多數情況下,這些xml格式只有乙個主資料項元素掛在根節點的正下方,並且重複了數千次

在這種情況下,最好讓lxml.etree來構建樹,並且只擷取這乙個元素,使用普通的樹api來提取資料

xml_file = bytesio(b'''\

abcabc

more datamore data

xyzxyz

''')

for _, element in etree.iterparse(xml_file, tag='a'):

print('%s -- %s' % (element.findtext('b'), element[1].text))

element.clear(keep_tail=true)

'''輸出:

abc -- abc

more data -- more data

xyz -- xyz

'''

如果出於某種原因根本不需要構建樹,則可以使用lxml.etree的目標解析器介面

它通過呼叫目標物件的方法建立類似sax的事件。通過實現部分或全部這些方法,可以控制生成哪些事件

class parsertarget:

events =

close_count = 0

def start(self, tag, attrib):

def close(self):

events, self.events = self.events,

self.close_count += 1

return events

parser_target = parsertarget()

parser = etree.xmlparser(target=parser_target)

events = etree.fromstring('', parser)

print(parser_target.close_count) #輸出:1

for event in events:

print('event: %s - tag: %s' % (event[0], event[1]))

for attr, value in event[2].items():

print(' * %s = %s' % (attr, value))

'''輸出:

event: start - tag: root

* test = true

'''

可隨時重用解析器及其目標,因此要確保.close()方法確實已將目標狀態重置為可用(在出現錯誤時也是如此!)

events = etree.fromstring('', parser)

print(parser_target.close_count) #輸出:2

events = etree.fromstring('', parser)

print(parser_target.close_count) #輸出:3

events = etree.fromstring('', parser)

print(parser_target.close_count) #輸出:4

for event in events:

print('event: %s - tag: %s' % (event[0], event[1]))

for attr, value in event[2].items():

print(' * %s = %s' % (attr, value))

'''輸出:

event: start - tag: root

* test = true

'''

事件驅動解析

有時我們需要的只是樹內某個地方的一小部分,因此將整個樹解析到記憶體中,全體遍歷並進行相關操作造成的記憶體開銷會很大 因此,etree提供了兩個事件驅動的解析器介面 乙個是在構建樹時,生成解析器事件 iterparse 另乙個根本不構建樹,而是以類似sax的方式呼叫目標物件的反饋方法 some fil...

驅動python python實現事件驅動

eventmanager事件管理類實現,大概就百來行 左右。encoding utf 8 系統模組 from queue import queue,empty from threading import class eventmanager def init self 初始化事件管理器 事件物件列表...

事件驅動與流程驅動

1 流程驅動 類似 一般就是主動輪詢 在幹活中還要分心 主動去找活幹 這樣有空餘的時間也完全浪費掉了 2 事件驅動 類似 比如公司有乙個oa系統 你幹完活的時候只需要看下oa系統有沒分配給你活 沒有可以幹自己的事 不用擔心還有其他事沒幹完 3者對比 採用警覺式者主動去輪詢 polling 行為取決於...