2017-06-06 25 views
0

いつも実行中のツールで書き込まれているXMLファイルを監視する必要があります。しかし、XMLファイルは適切に完成し、終わりにのみ閉じられます。 XMLストリーム処理などXMLファイルの読み込み中(Pythonで)

同じ制約:

  1. オンザフライとトリガーアクション
  2. 不完全なXMLファイルを解析し、最初から再度の処理を回避するために、ファイル内の最後の位置を追跡しますNeed to read XML files as a stream using BeautifulSoup in Pythonの答えに

slezicaxml.saxxml.etree.ElementTreecElementTree示唆しています。しかし、xml.etree.ElementTreecElementTreeを使用しようとした私の試みは成功しませんでした。 xml.dom,xml.parsers.expatおよびlxmlもありますが、「オンザフライ解析」のサポートは表示されません。

私はより多くの明白な例が必要...

私は現在、Linux上のPython 2.7を使用していますが、私は、Python 3.xのに移行します=>新しいPythonの3.xの機能に関するヒントを提供してください。また、watchdogを使用してXMLファイルの変更を検出することもできます。>オプションで、watchdogメカニズムを再利用します。オプションでWindowsもサポートします。

ソリューションを理解しやすい/維持するを提供してください。複雑すぎる場合は、tell()/seek()をファイル内で移動し、生のXMLで愚かなテキスト検索を使用し、最後に基本正規表現を使用して値を抽出することがあります。


XMLサンプル:SAXを使用して

<dfxml xmloutputversion='1.0'> 
    <creator version='1.0'> 
    <program>TCPFLOW</program> 
    <version>1.4.6</version> 
    </creator> 
    <configuration> 
    <fileobject> 
     <filename>file1</filename> 
     <filesize>288</filesize> 
     <tcpflow packets='12' srcport='1111' dstport='2222' family='2' /> 
    </fileobject> 
    <fileobject> 
     <filename>file2</filename> 
     <filesize>352</filesize> 
     <tcpflow packets='12' srcport='3333' dstport='4444' family='2' /> 
    </fileobject> 
    <fileobject> 
     <filename>file3</filename> 
     <filesize>456</filesize> 
     ... 
     ... 

最初のテストに失敗しました:

import xml.sax 

class StreamHandler(xml.sax.handler.ContentHandler): 
    def startElement(self, name, attrs): 
     print 'start: name=', name 
    def endElement(self, name): 
     print 'end: name=', name 
     if name == 'root': 
      raise StopIteration 

if __name__ == '__main__': 
    parser = xml.sax.make_parser() 
    parser.setContentHandler(StreamHandler()) 
    with open('f.xml') as f: 
     parser.parse(f) 

シェル:

$ while read line; do echo $line; sleep 1; done <i.xml >f.xml & 
... 
$ ./test-using-sax.py 
start: name= dfxml 
start: name= creator 
start: name= program 
end: name= program 
start: name= version 
end: name= version 
Traceback (most recent call last): 
    File "./test-using-sax.py", line 17, in <module> 
    parser.parse(f) 
    File "/usr/lib64/python2.7/xml/sax/expatreader.py", line 107, in parse 
    xmlreader.IncrementalParser.parse(self, source) 
    File "/usr/lib64/python2.7/xml/sax/xmlreader.py", line 125, in parse 
    self.close() 
    File "/usr/lib64/python2.7/xml/sax/expatreader.py", line 220, in close 
    self.feed("", isFinal = 1) 
    File "/usr/lib64/python2.7/xml/sax/expatreader.py", line 214, in feed 
    self._err_handler.fatalError(exc) 
    File "/usr/lib64/python2.7/xml/sax/handler.py", line 38, in fatalError 
    raise exception 
xml.sax._exceptions.SAXParseException: report.xml:15:0: no element found 

答えて

0

3時間を私の質問を投稿した後、回答は得られませんでした。しかし、私は最終的に私が探していた簡単な例を実装しました。

私のインスピレーションは、saajanswerであり、xml.saxwatchdogに基づいています。

from __future__ import print_function, division 
import time 
import watchdog.events 
import watchdog.observers 
import xml.sax 

class XmlStreamHandler(xml.sax.handler.ContentHandler): 
    def startElement(self, tag, attributes): 
    print(tag, 'attributes=', attributes.items()) 
    self.tag = tag 
    def characters(self, content): 
    print(self.tag, 'content=', content) 

class XmlFileEventHandler(watchdog.events.PatternMatchingEventHandler): 
    def __init__(self): 
    watchdog.events.PatternMatchingEventHandler.__init__(self, patterns=['*.xml']) 
    self.file = None 
    self.parser = xml.sax.make_parser() 
    self.parser.setContentHandler(XmlStreamHandler()) 
    def on_modified(self, event): 
    if not self.file: 
     self.file = open(event.src_path) 
    self.parser.feed(self.file.read()) 

if __name__ == '__main__': 
    observer = watchdog.observers.Observer() 
    event_handler = XmlFileEventHandler() 
    observer.schedule(event_handler, path='.') 
    try: 
    observer.start() 
    while True: 
     time.sleep(10) 
    finally: 
    observer.stop() 
    observer.join() 

スクリプトが実行されている間、touch 1つのXMLファイルに忘れてはいけない、または次のコマンドを使用してオンザフライ書き込みをシミュレート:昨日から

while read line; do echo $line; sleep 1; done <in.xml >out.xml & 
1

を私は "Peter Gibsonを見つけましたs answerについて書かれていますxml.etree.ElementTree.XMLTreeBuilder._parser.EndElementHandler

この例は、他の例と似ていますが、xml.etree.ElementTree(およびwatchdog)を使用しています。

ElementTreecElementTreeに置き換えられたときにそれは動作しません: - スクリプトが実行されている間、touch 1つのXMLファイルに忘れて、またはこれを使用してオンザフライ書き込みをシミュレートしていない/

import time 
import watchdog.events 
import watchdog.observers 
import xml.etree.ElementTree 

class XmlFileEventHandler(watchdog.events.PatternMatchingEventHandler): 
    def __init__(self): 
     watchdog.events.PatternMatchingEventHandler.__init__(self, patterns=['*.xml']) 
     self.xml_file = None 
     self.parser = xml.etree.ElementTree.XMLTreeBuilder() 
     def end_tag_event(tag): 
      node = self.parser._end(tag) 
      print 'tag=', tag, 'node=', node 
     self.parser._parser.EndElementHandler = end_tag_event 

    def on_modified(self, event): 
     if not self.xml_file: 
      self.xml_file = open(event.src_path) 
     buffer = self.xml_file.read() 
     if buffer: 
      self.parser.feed(buffer) 

if __name__ == '__main__': 
    observer = watchdog.observers.Observer() 
    event_handler = XmlFileEventHandler() 
    observer.schedule(event_handler, path='.') 
    try: 
     observer.start() 
     while True: 
      time.sleep(10) 
    finally: 
     observer.stop() 
     observer.join() 

1行スクリプト:情報について

while read line; do echo $line; sleep 1; done <in.xml >out.xml & 

xml.etree.ElementTree.iterparseが書き込まれているファイルをサポートしていないようです。私のテストコード:

from __future__ import print_function, division 
import xml.etree.ElementTree 

if __name__ == '__main__': 
    context = xml.etree.ElementTree.iterparse('f.xml', events=('end',)) 
    for action, elem in context: 
     print(action, elem.tag) 

マイ出力:

end program 
end version 
end creator 
end filename 
end filesize 
end tcpflow 
end fileobject 
end filename 
end filesize 
end tcpflow 
end fileobject 
end filename 
end filesize 
Traceback (most recent call last): 
    File "./iter.py", line 9, in <module> 
    for action, elem in context: 
    File "/usr/lib64/python2.7/xml/etree/ElementTree.py", line 1281, in next 
    self._root = self._parser.close() 
    File "/usr/lib64/python2.7/xml/etree/ElementTree.py", line 1654, in close 
    self._raiseerror(v) 
    File "/usr/lib64/python2.7/xml/etree/ElementTree.py", line 1506, in _raiseerror 
    raise err 
xml.etree.ElementTree.ParseError: no element found: line 20, column 0 
関連する問題