lxml.etree.iterparse закрывает обработчик входного файла? - PullRequest
5 голосов
/ 24 июля 2011

filterous равно с использованием iterparse для анализа простого XML StringIO объекта в модульном тесте .Однако при попытке доступа к объекту StringIO впоследствии Python завершает работу с сообщением «ValueError: I/O operation on closed file».Согласно документации iterparse «Начиная с lxml 2.3, метод .close () также будет вызываться в случае ошибки», но я не получаю сообщения об ошибке или Exception из iterparse,Мой IO-foo явно не на высоте, так что у кого-нибудь есть предложения?

Команда и (надеюсь) соответствующий код:

$ python2.6 setup.py test

setup.py:

from setuptools import setup
from filterous import filterous as package

setup(
    ...
    test_suite = 'tests.tests',

tests / tests.py:

from cStringIO import StringIO
import unittest

from filterous import filterous

XML = '''<posts tag="" total="3" ...'''

class TestSearch(unittest.TestCase):
    def setUp(self):
        self.xml = StringIO(XML)
        self.result = StringIO()
    ...
    def test_empty_tag_not(self):
        """Empty tag; should get N results."""
        filterous.search(
            self.xml,
            self.result,
            {'ntag': [u'']},
            ['href'],
            False)
        self.assertEqual(
            len(self.result.getvalue().splitlines()),
            self.xml.getvalue().count('<post '))

filterous / filterous.py:

from lxml import etree
...
def search(file_pointer, out, terms, includes, human_readable = True):
    ...
    context = etree.iterparse(file_pointer, tag='posts')

Traceback:

ERROR: Empty tag; should get N results.
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/home/victor/dev/filterous/tests/tests.py", line 149, in test_empty_tag_not
    self.xml.getvalue().count('<post '))
ValueError: I/O operation on closed file

PS: все тестыработает нормально 2010-07-27 .

Ответы [ 2 ]

1 голос
/ 24 июля 2011

Кажется, работает нормально с StringIO, попробуйте использовать это вместо cStringIO.Не знаю, почему это закрывается.

0 голосов
/ 24 июля 2011

Док-фу это проблема. То, что вы цитировали «Начиная с lxml 2.3, метод .close () также будет вызываться в случае ошибки», никак не связано с iterparse. Он появляется на вашей связанной странице перед разделом iterparse. Это часть документации для целевого интерфейса анализатора. Он ссылается на метод close () целевого (выходного!) Объекта, никак не связанный с вашим StringIO. В любом случае, вы также, кажется, проигнорировали это маленькое слово также . До 2.3 lxml закрывал целевой объект, только если анализ был успешным. Теперь он также закрывает его при ошибке.

Почему вы хотите "получить доступ" к объекту StringIO после завершения анализа?

Обновление Пытаясь впоследствии получить доступ к базе данных, подразумеваете ли вы все эти вызовы self.xml.getvalue () в ваших тестах? [Показать трассировку ferschlugginer в вашем вопросе, чтобы нам не приходилось догадываться!] Если это вызывает проблему (она считается операцией ввода-вывода), забудьте getvalue () ... если бы это работало, не так ли вернуть (нетрадиционно названный) (инвариантный) XML?

...