Анализатор lxml ест всю память
Я пишу паук в python и использую библиотеку lxml для разбора html и gevent-библиотеки для async. Я обнаружил, что после некоторого времени работы lxml parser начинает ест память до 8 ГБ (вся память сервера). Но у меня есть только 100 асинхронных потоков, каждый из которых анализирует документ max до 300 КБ.
i'v протестирован и эта проблема начинается с lxml.html.fromstring, но я не могу воспроизвести эту проблему.
Проблема в этой строке кода:
HTML = lxml.html.fromstring(htmltext)
Возможно, кто-то знает, что это может быть, или мотыги, чтобы исправить это?
Спасибо за помощь.
P.S.
Linux Debian-50-lenny-64-LAMP 2.6.26-2-amd64 #1 SMP Tue Jan 25 05:59:43 UTC 2011 x86_64 GNU/Linux
Python : (2, 6, 6, 'final', 0)
lxml.etree : (2, 3, 0, 0)
libxml used : (2, 7, 8)
libxml compiled : (2, 7, 8)
libxslt used : (1, 1, 26)
libxslt compiled : (1, 1, 26)
UP:
i установить ulimit -Sv 500000 и uliit -Sm 615000 для процессов, использующих парсер lxml.
И теперь через некоторое время они начинают записывать в журнал ошибок:
"Exception MemoryError: MemoryError() в 'lxml.etree._BaseErrorLog._receive" игнорируется ".
И я не могу поймать это исключение, поэтому он рекурсивно записывает в журнале это сообщение unile, на диске есть свободное место.
Как я могу поймать это исключение, чтобы убить процесс, чтобы демон мог создать новый?
Ответы
Ответ 1
Возможно, вы держите ссылки, которые хранят документы. Будьте осторожны с строковыми результатами оценки xpath, например: по умолчанию они являются "умными" строками, которые обеспечивают доступ к содержащемуся элементу, тем самым сохраняя дерево в памяти, если вы сохраняете ссылку на них. См. Документы в значениях возврата xpath:
Существуют определенные случаи, когда поведение интеллектуальной строки нежелательно. Например, это означает, что дерево будет поддерживаться в строке, что может иметь значительное влияние на память в случае, когда строковое значение является единственной вещью в дереве, которая действительно представляет интерес. В этих случаях вы можете отключить родительские отношения, используя аргумент ключевого слова smart_strings.
(я понятия не имею, если это проблема в вашем случае, но это кандидат. Я был укушен этим сам однажды; -))
Ответ 2
В http://www.lshift.net/blog/2008/11/14/tracing-python-memory-leaks, которая демонстрирует графическую отладку структур памяти; это может помочь вам понять, что не выпущено и почему.
Изменить: Я нашел статью, из которой я получил эту ссылку - Утечки памяти Python
Ответ 3
Похоже, что проблема связана с библиотекой lxml, основанной на: libxml2, которая написана на языке C.
Вот первый отчет: http://codespeak.net/pipermail/lxml-dev/2010-December/005784.html
Эта ошибка не упоминалась ни в журналах исправлений ошибок lxml v2.3, ни в журналах изменений libxml2.
О, здесь есть следующие сообщения: https://bugs.launchpad.net/lxml/+bug/728924
Ну, я попытался воспроизвести проблему, но ничего не получаю. Ребята, которые могут его воспроизвести, могут помочь в выяснении проблемы.