Чтение одного и того же файла несколько раз в Python - PullRequest
3 голосов
/ 18 декабря 2009

Мне нужно скачать zip-архив текстовых файлов, отправить каждый текстовый файл в архиве другим обработчикам для обработки и, наконец, записать разархивированный текстовый файл на диск.

У меня есть следующий код. Он использует несколько открытых / закрытых для одного и того же файла, что не выглядит элегантно. Как мне сделать его более элегантным и эффективным?

zipped = urllib.urlopen('www.abc.com/xyz.zip')
buf = cStringIO.StringIO(zipped.read())
zipped.close()
unzipped = zipfile.ZipFile(buf, 'r')
for f_info in unzipped.infolist():
   logfile = unzipped.open(f_info)
   handler1(logfile)
   logfile.close()   ## Cannot seek(0). The file like obj does not support seek()
   logfile = unzipped.open(f_info)
   handler2(logfile)
   logfile.close()
   unzipped.extract(f_info)

Ответы [ 3 ]

5 голосов
/ 18 декабря 2009

Ваш ответ в вашем примере кода. Просто используйте StringIO для буферизации файла журнала:

zipped = urllib.urlopen('www.abc.com/xyz.zip')
buf = cStringIO.StringIO(zipped.read())
zipped.close()
unzipped = zipfile.ZipFile(buf, 'r')
for f_info in unzipped.infolist():
   logfile = unzipped.open(f_info)
   # Here's where we buffer:
   logbuffer = cStringIO.StringIO(logfile.read())
   logfile.close()

   for handler in [handler1, handler2]:
      handler(logbuffer)
      # StringIO objects support seek():
      logbuffer.seek(0)

   unzipped.extract(f_info)
1 голос
/ 18 декабря 2009

Откройте zip-файл один раз, переберите все имена, извлеките файл для каждого имени и обработайте его, затем запишите его на диск.

Вроде так:

for f_info in unzipped.info_list():
    file = unzipped.open(f_info)
    data = file.read()
    # If you need a file like object, wrap it in a cStringIO
    fobj = cStringIO.StringIO(data)
    handler1(fobj)
    handler2(fobj)
    with open(filename,"w") as fp:
        fp.write(data)

Вы поняли

1 голос
/ 18 декабря 2009

Вы могли бы сказать что-то вроде:

handler_dispatch(logfile)

и

def handler_dispatch(file):
   for line in file:
      handler1(line)
      handler2(line)

или даже сделать его более динамичным, создав класс Handler с несколькими функциями handlerN и применив каждую из них внутри handler_dispatch. Как

class Handler:
    def __init__(self:)
        self.handlers = []

  def add_handler(handler):
      self.handlers.append(handler)

  def handler_dispatch(self, file):
      for line in file:
          for handler in self.handlers:
              handler.handle(line)
...