Могу ли я по-прежнему использовать StringIO, когда содержащийся Writer () закрывает его? - PullRequest
1 голос
/ 02 апреля 2012

Я использую Python avro library .Я хочу отправить файл avro через http, но я не хочу сначала сохранять этот файл на диск, поэтому я решил использовать StringIO для хранения содержимого файла, пока не буду готов к отправке.Но avro.datafile.DataFileWriter тщательно заботится о том, чтобы закрыть для меня дескриптор файла, что затрудняет мне получение данных из StringIO.Вот что я имею в виду в коде:

from StringIO import StringIO
from avro.datafile import DataFileWriter
from avro import schema, io
from testdata import BEARER, PUBLISHURL, SERVER, TESTDATA
from httplib2 import Http

HTTP = Http()
##
# Write the message data to a StringIO
#
# @return StringIO
#
def write_data():
    message = TESTDATA
    schema = getSchema()
    datum_writer = io.DatumWriter(schema)
    data = StringIO()
    with DataFileWriter(data, datum_writer, writers_schema=schema, codec='deflate') as datafile_writer:
        datafile_writer.append(message)
        # If I return data inside the with block, the DFW buffer isn't flushed
        # and I may get an incomplete file
    return data

##
# Make the POST and dump its response
#
def main():
    headers = {
        "Content-Type": "avro/binary",
        "Authorization": "Bearer %s" % BEARER,
        "X-XC-SCHEMA-VERSION": "1.0.0",
    }
    body = write_data().getvalue() # AttributeError: StringIO instance has no attribute 'buf'
    # the StringIO instance returned by write_data() is already closed. :(
    resp, content = HTTP.request(
        uri=PUBLISHURL,
        method='POST',
        body=body,
        headers=headers,
    )
    print resp, content

У меня есть некоторые обходные пути, которые я могу использовать, но ни один из них не является ужасно элегантным.Есть ли способ получить данные из StringIO после его закрытия?

Ответы [ 2 ]

3 голосов
/ 02 апреля 2012

Не совсем.

Документы очень ясны по этому вопросу:

StringIO.close ()

Освободить буфер памяти,Попытка выполнить дальнейшие операции с закрытым объектом StringIO вызовет ValueError.

Самый чистый способ сделать это - наследовать от StringIO и переопределить метод close, чтобы ничего не делать:

class MyStringIO(StringIO):
   def close(self):
       pass
   def _close(self):
       super(MyStringIO, self).close()

И позвоните _close(), когда будете готовы.

1 голос
/ 31 августа 2013

Я хотел сделать то же самое, у DataFileWriter есть метод сброса, поэтому вы должны иметь возможность сбрасывать после вызова, чтобы добавить, а затем вернуть данные. Мне кажется, это немного элегантнее, чем вывод класса из StringIO.

...