Отправляет email-рассылки с помощью сервиса Sendsay

[prg] Python: ZIP+ElementTree+FB2.

Здравствуйте.

Python 3.6
Win7

Возник тут у меня один вопрос. Я занимаюсь парсингом FB2-книг. При
этом использую класс ElementTree. Все замечательно, кроме нескольких
моментов. об ошибке ParseError на файлах CP1251 с некоторыми символами
как-нибудь в другой раз, а пока остановлюсь на проблеме анализа FB2 в
архивах.

Суть в следующем, я очень не хочу распаковывать файлы на диск. Ну в
самом-то деле, файлов этих у меня сотни тысяч...

А вот как сделать файловый объект в оперативной памяти, никак не
соображу.

Вышел из положения при помощи функции read объекта ZipFile. Передавая
ей имя анализируемого файла:

zf.read(fn)

На выходе получается байтовая строка, которую скармливаю функции
fromstring класса ElementTree.

В общем-то работает. Но ненадёжно к сожалению. Некоторые файлы таким
образом распарсить не получается. Исследования показали, что
fromstring почему-то теряет тег fictionbook, и возвращает список из
description и body.

Ну и вообще - получается объект element, а не ElementTree... Это тоже
как-то мне кажется неэстетичным.

В общем, хочу распаковать файл из архива в какую-нибудь переменную,
которую можно скормить ElementTree... Создавать что-либо на диске
не хочу категорически.

В общем, можно ли это как-то реализовать?

Если кто захочет поиграться, с удовольствием предоставлю и код и
битый файл.

Буду благодарен за любую помощь.

И позволю уж себе немножко поныть... :-)

Всегда казалось, что работа с zip-архивами - это одна из
востребованных практических задач при написании программ. В то же
время модуль zipfile производит впечатление какого-то уж больно
куцего, особенно, если сравнить с функционалом графических
архиваторов. Например, я так и не смог сообразить, как можно
переименовать файл в архиве... Кстати, как-то совершенно не смог
скормить функции по упаковке параметр compression.
compression=ZIP_DEFLATE Python воспринимать не захотел от слова
совсем. Я даже в исходниках нашёл, как он там пишется, но так и
пришлось использовать цифровое значение нужного параметра...

В общем, Python, на первый взгляд кажется просто замечательным, но при
попытке решить какую-нибудь задачу, слегка выходящую за пределы
стандарта, постоянно сталкиваешься с какими-то непонятками, с которыми
неизвестно что делать.

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

Ответить   Mon, 4 Dec 2017 15:54:56 +0400 (#3533869)

 

Ответы:

Приветствую всех!

Устарел. Надо использовать xml.etree.cElementTree (это тот же API, но
реализован на C).

Не советую пренебрегать чтением документации. Это и есть штатное поведение
указанного метода: fromstring сразу возвращает корневой Element, а не
ElementTree.
Добавьте print и убедитесь:
root = et.fromstring(b)
print (root.tag)

Использование C++ для подобных задач -- похоже на использование самурайского
меча для заточки карандашей. Всё-таки для этого лучше использовать
карандашную точилку -- и безопасней, и результат можно получить с меньшими
усилиями.
К тому же, обсуждаемая проблема не имеет отношения к используемому языку
программирования, а связана с библиотеками тех или иных API. В C++ вам тоже
придётся разбираться с ними, но только код не будет таким прозрачным и
простым, как в python.

Успехов. Анатолий.

Ответить   "i_chay" Mon, 4 Dec 2017 20:55:01 +0300 (#3533955)

 

Здравствуйте, i_chay.

Я согласен с предыдущим оратором и вообще сказал бы, что ожидать снижение
микроменеджмента с понижением уровня языка точно не стоит. (Уровня
абстракции, а не качества.) Если нужно "освободить руки" и сделать жизнь
проще, то это точно не путь от Python к C++.
Переход к более низкоуровневым языкам оправдан, когда вы задыхаетесь от
нехватки ресурсов или страдаете от низкой производительности. Ну ещё когда
вам нужно повысить переносимость кода между разными платформами, хотя в
случае Python я бы тут тоже усомнился.
Ну а если есть чисто эстетическое пристрастие к стилю C-синтаксиса, то с
Python логичнее переходить на C#.

Возвращаясь к теме, у zipfile, в принципе, есть сторонние альтернативы, как
минимум, czipfile. Ставится просто через pip:
pip install czipfile
Правда это больше про прирост производительности, чем про прирост
функциональности. Набор функций у него практически аналогичный. Ещё я не
помню, что там с Python 3, надо уточнять, если для вас это важно.
Также всю работу с архивами вообще можно переложить на внешний компонент,
например, на консольный 7Zip, но это скорей если реально нужно распаковывать
и запаковывать.
Успехов. Никита.

Ответить   Mon, 4 Dec 2017 21:51:02 +0300 (#3533977)

 

Приветствую всех!

Одну букву забыли:

import zipfile
print(zipfile.ZIP_DEFLATED)
Вывод: 8

Чтобы переименовать или удалить файл в zip-архиве при помощи zipfile
придётся открыть новый ZipFile для записи и скопировать в него требуемые
файлы (заменяя, если нужно, их архивные имена).

Успехов. Анатолий.

Ответить   "i_chay" Tue, 5 Dec 2017 11:47:46 +0300 (#3534053)