[Python] Проблема с xml.etree.cElementTree
От: SmaLL75 Россия http://smallweb.narod.ru
Дата: 28.09.17 07:00
Оценка:
Здравствуйте!

Версии Python:
Python 2.7.13 (v2.7.13:a06454b1afa1, Dec 17 2016, 20:53:40) [MSC v.1500 64 bit (AMD64)] on win32
Python 3.6.2 (v3.6.2:5fd33b5, Jul 8 2017, 04:57:36) [MSC v.1900 64 bit (AMD64)] on win32
Python 3.6.2 (default, Jul 20 2017, 08:43:29) [GCC 4.9.4] on linux

Обрабатывается большой xml-файл ~100мб (это не предел)

Используется функция последовательного разбора xml из пакета xml.etree.cElementTree

for event, elem in ET.iterparse(xml, events=('start', 'end')):
    if event is "start":
....


Проблема в том, что при использовании iterparse пропускаются данные.

Это баг или фича? Можно ли решить или обойти проблему?

  пример xml
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<pivotCacheRecords xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" count="236834">
<r>
<s v="3632025024"/>
<x v="0"/>
<x v="0"/>
<x v="0"/>
<x v="0"/>
<x v="0"/>
<x v="0"/>
<x v="0"/>
<x v="0"/>
<x v="0"/>
<x v="0"/>
<x v="0"/>
<x v="0"/>
<x v="0"/>
<x v="0"/>
<x v="0"/>
<n v="1"/>
<x v="0"/>
<x v="0"/>
<x v="0"/>
<s v="177230"/>
<x v="0"/>
<x v="0"/>
<x v="0"/>
<x v="0"/>
<x v="0"/>
<x v="0"/>
<x v="0"/>
<x v="0"/>
<d v="2014-10-17T00:00:00"/>
<n v="1051"/>
<x v="0"/>
<x v="0"/>
</r>
<r>
<s v="3632369876"/>
<x v="0"/>
<x v="0"/>
<x v="0"/>
<x v="0"/>
<x v="0"/>
<x v="1"/>
<x v="1"/>
<x v="1"/>
<x v="0"/>
<x v="0"/>
<x v="0"/>
<x v="0"/>
<x v="0"/>
<x v="0"/>
<x v="0"/>
<n v="1"/>
<x v="0"/>
<x v="1"/>
<x v="0"/>
<s v="214239"/>
<x v="0"/>
<x v="1"/>
<x v="0"/>
<x v="1"/>
<x v="1"/>
<x v="0"/>
<x v="0"/>
<x v="0"/>
<d v="2016-07-22T00:00:00"/>
<n v="407"/>
<x v="1"/>
<x v="0"/>
</r>
Что ни делается, всЁ к лучшему
Отредактировано 28.09.2017 7:51 SmaLL75 . Предыдущая версия .
python xml elementtree
Re: [Python] Проблема с xml.etree.cElementTree
От: Senyai Россия http://www.arseniy.net
Дата: 28.09.17 10:21
Оценка:
Здравствуйте, SmaLL75, Вы писали:

SLL>
SLL>for event, elem in ET.iterparse(xml, events=('start', 'end')):
SLL>    if event is "start":
SLL>....
SLL>


Как минимум "is" нельзя использовать для сравнения строк.
Не бойтесь совершенства. Вам его не достичь. © Сальвадор Дали
Re[2]: [Python] Проблема с xml.etree.cElementTree
От: SmaLL75 Россия http://smallweb.narod.ru
Дата: 28.09.17 11:01
Оценка:
Здравствуйте, Senyai, Вы писали:

S>Здравствуйте, SmaLL75, Вы писали:


SLL>>
SLL>>for event, elem in ET.iterparse(xml, events=('start', 'end')):
SLL>>    if event is "start":
SLL>>....
SLL>>


S>Как минимум "is" нельзя использовать для сравнения строк.


можно или нельзя, но условие работает и это ни каким образом не может быть причиной пропуска данных, т.е. в elem должно быть всегда 33 элемента, а в действительности это количество меняется хаотично
Что ни делается, всЁ к лучшему
Re[3]: [Python] Проблема с xml.etree.cElementTree
От: Senyai Россия http://www.arseniy.net
Дата: 28.09.17 11:12
Оценка:
Здравствуйте, SmaLL75, Вы писали:

SLL>можно или нельзя, но условие работает и это ни каким образом не может быть причиной пропуска данных, т.е. в elem должно быть всегда 33 элемента, а в действительности это количество меняется хаотично


Простите, вы утверждаете, что условие "is" работает? Оно как раз хаотично работает. Замените на "==".
Не бойтесь совершенства. Вам его не достичь. © Сальвадор Дали
Re[4]: [Python] Проблема с xml.etree.cElementTree
От: SmaLL75 Россия http://smallweb.narod.ru
Дата: 28.09.17 11:37
Оценка:
Здравствуйте, Senyai, Вы писали:

S>Здравствуйте, SmaLL75, Вы писали:


SLL>>можно или нельзя, но условие работает и это ни каким образом не может быть причиной пропуска данных, т.е. в elem должно быть всегда 33 элемента, а в действительности это количество меняется хаотично


S>Простите, вы утверждаете, что условие "is" работает? Оно как раз хаотично работает. Замените на "==".


Спасибо за участие, но ничего не изменилось.

for event, elem in ET.iterparse(xml, events=('start', 'end')):
    record = {}
    if event == "start":
        if elem.tag == "{http://schemas.openxmlformats.org/spreadsheetml/2006/main}r":
            for rnum, item in enumerate(elem):
                if len(elem) != 33 and rnum ==0:
                    print(item.attrib['v'])
                record.update({rnum: item.attrib['v']})
            rec = list(record.values())
            record.clear()
            f.write(";".join(rec) + "\n")
    elem.clear()
Что ни делается, всЁ к лучшему
Re[5]: [Python] Проблема с xml.etree.cElementTree
От: Senyai Россия http://www.arseniy.net
Дата: 28.09.17 12:05
Оценка:
Здравствуйте, SmaLL75, Вы писали:

SLL>Здравствуйте, Senyai, Вы писали:


S>>Здравствуйте, SmaLL75, Вы писали:


SLL>>>можно или нельзя, но условие работает и это ни каким образом не может быть причиной пропуска данных, т.е. в elem должно быть всегда 33 элемента, а в действительности это количество меняется хаотично


S>>Простите, вы утверждаете, что условие "is" работает? Оно как раз хаотично работает. Замените на "==".


SLL>Спасибо за участие, но ничего не изменилось.


SLL>
SLL>for event, elem in ET.iterparse(xml, events=('start', 'end')):
SLL>    record = {}
SLL>    if event == "start":
SLL>        if elem.tag == "{http://schemas.openxmlformats.org/spreadsheetml/2006/main}r":
SLL>            for rnum, item in enumerate(elem):
SLL>                if len(elem) != 33 and rnum ==0:
SLL>                    print(item.attrib['v'])
SLL>                record.update({rnum: item.attrib['v']})
SLL>            rec = list(record.values())
SLL>            record.clear()
SLL>            f.write(";".join(rec) + "\n")
SLL>    elem.clear()
            
SLL>


На приведённом в первом посте xml, в f записывается:

3632025024;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;1;0;0;0;177230;0;0;0;0;0;0;0;0;2014-10-17T00:00:00;1051;0;0\n'
3632369876;0;0;0;0;0;1;1;1;0;0;0;0;0;0;0;1;0;1;0;214239;0;1;0;1;1;0;0;0;2016-07-22T00:00:00;407;1;0\n'


что выглядит правильно. Как повторить пропуск данных? (афк 1 час)
Не бойтесь совершенства. Вам его не достичь. © Сальвадор Дали
Re[6]: [Python] Проблема с xml.etree.cElementTree
От: SmaLL75 Россия http://smallweb.narod.ru
Дата: 28.09.17 13:42
Оценка:
Здравствуйте, Senyai, Вы писали:

S>Здравствуйте, SmaLL75, Вы писали:


SLL>>Здравствуйте, Senyai, Вы писали:


S>>>Здравствуйте, SmaLL75, Вы писали:


SLL>>>>можно или нельзя, но условие работает и это ни каким образом не может быть причиной пропуска данных, т.е. в elem должно быть всегда 33 элемента, а в действительности это количество меняется хаотично


S>>>Простите, вы утверждаете, что условие "is" работает? Оно как раз хаотично работает. Замените на "==".


SLL>>Спасибо за участие, но ничего не изменилось.


SLL>>
SLL>>for event, elem in ET.iterparse(xml, events=('start', 'end')):
SLL>>    record = {}
SLL>>    if event == "start":
SLL>>        if elem.tag == "{http://schemas.openxmlformats.org/spreadsheetml/2006/main}r":
SLL>>            for rnum, item in enumerate(elem):
SLL>>                if len(elem) != 33 and rnum ==0:
SLL>>                    print(item.attrib['v'])
SLL>>                record.update({rnum: item.attrib['v']})
SLL>>            rec = list(record.values())
SLL>>            record.clear()
SLL>>            f.write(";".join(rec) + "\n")
SLL>>    elem.clear()
            
SLL>>


S>На приведённом в первом посте xml, в f записывается:


S>
S>3632025024;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;1;0;0;0;177230;0;0;0;0;0;0;0;0;2014-10-17T00:00:00;1051;0;0\n'
S>3632369876;0;0;0;0;0;1;1;1;0;0;0;0;0;0;0;1;0;1;0;214239;0;1;0;1;1;0;0;0;2016-07-22T00:00:00;407;1;0\n'
S>


S>что выглядит правильно. Как повторить пропуск данных? (афк 1 час)


iterparse читает файл блоками по 16кб. Если файл меньше одного блока, то парсер работает нормально, но у меня файл 100мб.
Можно размножить блок с тегом "r" для создания файла необходимого объема.
Что ни делается, всЁ к лучшему
Re[7]: [Python] Проблема с xml.etree.cElementTree
От: Senyai Россия http://www.arseniy.net
Дата: 28.09.17 14:06
Оценка:
S>>На приведённом в первом посте xml, в f записывается:

S>>
S>>3632025024;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;1;0;0;0;177230;0;0;0;0;0;0;0;0;2014-10-17T00:00:00;1051;0;0\n'
S>>3632369876;0;0;0;0;0;1;1;1;0;0;0;0;0;0;0;1;0;1;0;214239;0;1;0;1;1;0;0;0;2016-07-22T00:00:00;407;1;0\n'
S>>


S>>что выглядит правильно. Как повторить пропуск данных? (афк 1 час)


SLL>iterparse читает файл блоками по 16кб. Если файл меньше одного блока, то парсер работает нормально, но у меня файл 100мб.

SLL>Можно размножить блок с тегом "r" для создания файла необходимого объема.

Замечательно — смог повторить.
Документация говорит, что на событии "start" все элементы не будут доступны:

Note
iterparse() only guarantees that it has seen the “>” character of a starting tag when it emits a “start” event, so the attributes are defined, but the contents of the text and tail attributes are undefined at that point. The same applies to the element children; they may or may not be present.
If you need a fully populated element, look for “end” events instead.


Я попробовал заменить на "end" и всё выглядит как надо. Главное elem.clear() не вызывать когда не надо, иначе attrib будет пустой.
Не бойтесь совершенства. Вам его не достичь. © Сальвадор Дали
Re[8]: [Python] Проблема с xml.etree.cElementTree
От: SmaLL75 Россия http://smallweb.narod.ru
Дата: 03.10.17 06:45
Оценка:
Здравствуйте, Senyai, Вы писали:

S>>>На приведённом в первом посте xml, в f записывается:


S>>>
S>>>3632025024;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;1;0;0;0;177230;0;0;0;0;0;0;0;0;2014-10-17T00:00:00;1051;0;0\n'
S>>>3632369876;0;0;0;0;0;1;1;1;0;0;0;0;0;0;0;1;0;1;0;214239;0;1;0;1;1;0;0;0;2016-07-22T00:00:00;407;1;0\n'
S>>>


S>>>что выглядит правильно. Как повторить пропуск данных? (афк 1 час)


SLL>>iterparse читает файл блоками по 16кб. Если файл меньше одного блока, то парсер работает нормально, но у меня файл 100мб.

SLL>>Можно размножить блок с тегом "r" для создания файла необходимого объема.

S>Замечательно — смог повторить.

S>Документация говорит, что на событии "start" все элементы не будут доступны:
S>

S>Note
S>iterparse() only guarantees that it has seen the “>” character of a starting tag when it emits a “start” event, so the attributes are defined, but the contents of the text and tail attributes are undefined at that point. The same applies to the element children; they may or may not be present.
S>If you need a fully populated element, look for “end” events instead.


S>Я попробовал заменить на "end" и всё выглядит как надо. Главное elem.clear() не вызывать когда не надо, иначе attrib будет пустой.


Спасибо, добрый человек!
Все заработало.
Что ни делается, всЁ к лучшему
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.