簡體   English   中英

使用lxml.etree.iterparse的線程問題

[英]threading issues using lxml.etree.iterparse

我有一個線程,它產生多個使用者進程,這些進程對大型xml文件進行大量處理。

為此,我的設計是使用一個簡單的單線程動態分析入站流,並將新對象推送到緩沖區進程管理器中包含的multiprocessing.queues.queue類中。 流程管理器會定期檢查隊列的大小,如果消耗量使隊列填充得太快,則會啟動另一個消耗者。

我的問題是流解析完成時要加入關閉隊列的代碼是在xml完成​​解析之前執行的! 在我看來,這似乎不應該是以下代碼的工作方式。 請記住,以下代碼是完全單線程的。 任何SMP代碼都不會調用或使用它:

clear_ok = False
context = lxml.etree.iterparse(response, events=('end',))
for event, elem in context:
    # Use QName to avoid specifying or stripping the namespace, which we don't need
    if lxml.etree.QName(elem.tag).localname.upper() in obj_elem_map:
        import_buffer.add(obj_elem_map[lxml.etree.QName(elem.tag).localname.upper()](elem=elem))
        clear_ok = True
    if clear_ok:
        elem.clear() #don't fill up a dom we don't need.
        clear_ok = False
results = import_buffer.finish() if block else import_buffer

調用import_buffer.finish()時,會發生以下情況:

def finish(self):
    '''
    Notifies the buffer that we are done filling it.
    This command binds to any processes still running and lets them
    finish and then copies and flushes the managed results list.
    '''
    # close the queue and wait until it is consumed
    self.queue.close()
    self.queue.join_thread()
    # make sure the consumers are done consuming the queue
    for csmr in self.running:
        csmr.join()
    # turn this into a list instead of a managed list
    result = list(self.results_list)
    del self.results_list[:]
    if self.callback:
        return self.callback(result)
    else:
        return result

但是我得到一個例外,就是我完成解析之前 ,已經在隊列上調用了close()?

Traceback (most recent call last):
  File "./tests/test_smp_framework.py", line 103, in test_kqb_parser_fromfile
    qkbobs = actions.queryQKB(file=fname)
  File "/Users/skyleach/src/smpparser/smpparser/api_actions.py", line 339, in queryQKB
    result = self.parseResponse(source=sourcefile)File "/Users/skyleach/src/smpparser/smpparser/smpapi.py", line 535, in parseResponse
    import_buffer.add(obj_elem_map[lxml.etree.QName(elem.tag).localname.upper()](elem=elem))
  File "/Users/skyleach/src/smpparser/smpparser/smpapi.py", line 212, in add
    self.queue.put(item)
  File "/usr/local/Cellar/python3/3.5.0/Frameworks/Python.framework/Versions/3.5/lib/python3.5/multiprocessing/queues.py", line 81, in put
    assert not self._closed
AssertionError

這不是lxml的錯誤或多處理的錯誤,這是上下文分配初始化問題。 基本上,我編碼太快了,犯了一個愚蠢的錯誤。

在我的緩沖區類定義中,我正在設置隊列,而不是在init函數中。 這意味着該類的所有實例的所有隊列都是由導入線程導入模塊時定義的一個隊列。

那就是我因為太快地編寫代碼而得到的。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM