2014-11-29 3 views
1

Я пытаюсь перенести некоторый код из Python 2.7 в Python 3. Инструмент 2to3 отлично работает для базового синтаксиса и изменений пакета, но теперь мы сталкиваемся с некоторыми странными побочными эффектами.Как использовать CSV Writers с файлами GZIP в Python 3?

У меня есть следующий блок кода. Он открывает временное имя файла, используя модуль gzip.

f = NamedTemporaryFile(delete=False) 
f.close() 
fn = f.name + '.gz' 
os.rename(f.name, fn) 
fz = gzip.open(fn, 'wb') 
writer = csv.writer(fz, delimiter='\t', lineterminator=lt) 
for row in table: 
    writer.writerow(row) 
fz.close() 

Проблема заключается в том, что выполнение этого дает мне следующую ошибку:

File "/usr/local/Cellar/python3/3.4.2_1/Frameworks/Python.framework/Versions/3.4/lib/python3.4/gzip.py", line 343, in write 
self.crc = zlib.crc32(data, self.crc) & 0xffffffff 
TypeError: 'str' does not support the buffer interface 

Я попытался открыть файл GZIP как «ш» вместо «термометра», но безрезультатно. Я предполагаю, что модуль gzip ожидает массив байтов, но CSV Writer не предоставляет или не предоставляет ничего, кроме строки.

Как люди делают это в Python 3?

Редактировать: Следует упомянуть, что этот блок кода выполняется без проблем в Python 2.7.

+0

Возможный дубликат http://stackoverflow.com/questions/7200606/python3-writing-csv-files –

+0

Несомненно, выглядит так, спасибо. Не знаю, почему я не мог найти этот вопрос, когда искал «python 3 csv writer» – WineSoaked

+0

Нет, мой вопрос различен. Это использует CSV Writer для дескриптора файла GZIP. Я получаю следующую ошибку, когда я пытаюсь выполнить 'fz = gzip.open (fn, 'wb', newline = '')': 'Файл '/usr/local/Cellar/python3/3.4.2_1/Frameworks/ Python.framework/Версии/3.4/lib/python3.4/gzip.py ", строка 48, в открытом Повысить ValueError (« Аргумент «новая строка» не поддерживается в двоичном режиме »)' 'ValueError: Argument 'newline' not поддерживается в двоичном режиме ' – WineSoaked

ответ

7

Вам нужно изменить режим gzip к wt:

fz = gzip.open(fn, 'wt') 

Также малоизвестная особенность gzip.open() и bz2.open() является то, что они могут быть многоуровневыми поверх существующего файла, открытого в бинарном режиме. Например, это работает:

import gzip 
f = open('somefile.gz', 'rb') 
with gzip.open(f, 'rt') as g: 
    text = g.read() 

Это позволяет GZIP и BZ2 модули для работы с различными файловыми как объекты, такие как розетки, трубы, и в памяти файлов.

+0

Yup, Python 3 означает, что вы должны быть очень ОЧЕНЬ осторожны с флагами, используемыми для открытия файлов. Человек, какая головная боль. – WineSoaked

+0

@WineSoaked :), да, а также малоизвестная функция 'gzip.open()' и 'bz2.open()' заключается в том, что они могут быть разбиты на слои поверх существующего файла, открытого в двоичном режиме. – Kasramvd

+0

Вы должны открыть для записи с помощью gzip.open (fn, 'wt', newline = '') ', в противном случае обработка новой строки csv может быть скомпрометирована (то есть: если запись csv имеет встроенную новую строку). – drevicko