有時我們需要的只是樹內某個地方的一小部分,因此將整個樹解析到記憶體中,全體遍歷並進行相關操作造成的記憶體開銷會很大
因此,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'
:
(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的事件。通過實現部分或全部這些方法,可以控制生成哪些事件
classparsertarget:
events =
close_count =0
defstart(self, tag, attrib):
"start
", tag, attrib))
defclose(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 行為取決於...