¿Cómo abrir un archivo de texto Unicode dentro de un zip?

Lo intenté

with zipfile.ZipFile("5.csv.zip", "r") as zfile: for name in zfile.namelist(): with zfile.open(name, 'rU') as readFile: line = readFile.readline() print(line) split = line.split('\t') 

responde:

 b'$0.0\t1822\t1\t1\t1\n' Traceback (most recent call last) File "zip.py", line 6 split = line.split('\t') TypeError: Type str doesn't support the buffer API 

¿Cómo abrir el archivo de texto como unicode en lugar de como b ?

para Python 3, usar io.TextIOWrapper como JF Sebastian describe es la mejor opción. La respuesta a continuación podría ser útil para 2.x. No creo que nada a continuación sea realmente incorrecto incluso para 3.x, pero io.TestIOWrapper es aún mejor.

Si el archivo es utf-8, esto funcionará:

 # the rest of the code as above, then: with zfile.open(name, 'rU') as readFile: line = readFile.readline().decode('utf8') # etc 

Si va a realizar una iteración sobre el archivo, puede usar codecs.iterdecode , pero eso no funcionará con readline() .

 with zfile.open(name, 'rU') as readFile: for line in codecs.iterdecode(readFile, 'utf8'): print line # etc 

Tenga en cuenta que ninguno de los enfoques es necesariamente seguro para las codificaciones multibyte. Por ejemplo, little-endian UTF-16 representa el carácter de nueva línea con los bytes b'\x0A\x00' . Una herramienta que no tenga en cuenta Unicode en busca de nuevas líneas se dividirá incorrectamente, dejando los bytes nulos en la línea siguiente. En tal caso, tendría que usar algo que no intente dividir la entrada por nuevas líneas, como ZipFile.read , y luego descodificar toda la cadena de bytes a la vez. Esto no es una preocupación para utf-8.

Para convertir un flujo de bytes en un flujo Unicode, puede usar io.TextIOWrapper() :

 encoding = 'utf-8' with zipfile.ZipFile("5.csv.zip") as zfile: for name in zfile.namelist(): with zfile.open(name) as readfile: for line in io.TextIOWrapper(readfile, encoding): print(repr(line)) 

Nota: TextIOWrapper() usa el modo de nueva línea universal de forma predeterminada. rU modo zfile.open() en zfile.open() está en desuso desde la versión 3.4.

Evita problemas con las codificaciones multibyte descritas en la respuesta de @Peter DeGlopper .

La razón por la que está viendo ese error es porque está intentando mezclar bytes con Unicode. El argumento para split también debe ser byte-string:

 >>> line = b'$0.0\t1822\t1\t1\t1\n' >>> line.split(b'\t') [b'$0.0', b'1822', b'1', b'1', b'1\n'] 

Para obtener una cadena de Unicode, use decodificar :

 >>> line.decode('utf-8') '$0.0\t1822\t1\t1\t1\n'