library - python get temp file
¿Cómo crear un archivo temporal con codificación Unicode? (7)
Dejar caer la u hizo que tu código funcionara para mí:
fh.write("Hello World: ä")
Supongo que es porque ya está unicode.
Cuando uso open()
para abrir un archivo, no puedo escribir cadenas Unicode. Aprendí que necesito usar codecs
y abrir el archivo con codificación Unicode (consulte http://docs.python.org/howto/unicode.html#reading-and-writing-unicode-data ).
Ahora necesito crear algunos archivos temporales. Intenté usar la biblioteca tempfile
, pero no tiene ninguna opción de codificación. Cuando intento escribir cualquier cadena Unicode en un archivo temporal con archivo temporal, falla:
#!/usr/bin/python2.6
# -*- coding: utf-8 -*-
import tempfile
with tempfile.TemporaryFile() as fh:
fh.write(u"Hello World: ä")
fh.seek(0)
for line in fh:
print line
¿Cómo puedo crear un archivo temporal con codificación Unicode en Python?
Editar:
Estoy usando Linux y el mensaje de error que recibo para este código es:
Traceback (most recent call last): File "tmp_file.py", line 5, in <module> fh.write(u"Hello World: ä") UnicodeEncodeError: ''ascii'' codec can''t encode character u''/xe4'' in position 13: ordinal not in range(128)
- Esto es solo un ejemplo. En la práctica, estoy tratando de escribir una cadena que devolvió alguna API.
Está intentando escribir un objeto Unicode (u"...")
en el archivo temporal donde debe usar una cadena codificada ("...")
. No tiene que pasar explícitamente un parámetro "encode="
, porque ya ha indicado la codificación en la línea dos ("# -*- coding: utf-8 -*-")
. Solo usa fh.write("ä")
lugar de fh.write(u"ä")
y estarás bien.
Establecer el sistema como codificación predeterminada en UTF-8 solucionará el problema de codificación
import sys
reload(sys)
sys.setdefaultencoding(''utf-8'') #set to utf-8 by default this will solve the errors
import tempfile
with tempfile.TemporaryFile() as fh:
fh.write(u"Hello World: ä")
fh.seek(0)
for line in fh:
print line
He descubierto una solución: cree un archivo temporal que no se elimine automáticamente con tempfile
, ciérrelo y ábralo nuevamente usando los codecs
:
#!/usr/bin/python2.6
# -*- coding: utf-8 -*-
import codecs
import os
import tempfile
f = tempfile.NamedTemporaryFile(delete=False)
filename = f.name
f.close()
with codecs.open(filename, ''w+b'', encoding=''utf-8'') as fh:
fh.write(u"Hello World: ä")
fh.seek(0)
for line in fh:
print line
os.unlink(filename)
Las respuestas de todos los demás son correctas, solo quiero aclarar lo que está pasando:
La diferencia entre el literal ''foo''
y el literal u''foo''
es que el primero es una cadena de bytes y el último es el objeto Unicode.
Primero, comprenda que Unicode es el conjunto de caracteres. UTF-8 es la codificación. El objeto Unicode es el anterior, es una cadena Unicode, no necesariamente una UTF-8. En su caso, la codificación de un literal de cadena será UTF-8, porque la especificó en las primeras líneas del archivo.
Para obtener una cadena Unicode de una cadena de bytes, llame al método .encode()
:
>>>> u"ひらがな".encode("utf-8") == "ひらがな"
True
De manera similar, puede llamar a su string.encode en la llamada de write
y lograr el mismo efecto que simplemente eliminando la u
.
Si no especificaste la codificación en la parte superior, di que si estuvieras leyendo los datos de Unicode de otro archivo, especificarías en qué codificación estaba antes de que alcanzara una cadena de Python. Esto determinaría cómo se representaría en bytes (es decir, el tipo str
).
El error que está recibiendo, entonces, es solo porque el módulo tempfile
está esperando un objeto str
. Esto no significa que no pueda manejar Unicode, solo que espera que pase una cadena de bytes en lugar de un objeto Unicode, ya que sin especificar una codificación, no sabría cómo escribirlo en el archivo temporal.
Ya que estoy trabajando en un programa de Python con objetos TemporaryFile que deberían ejecutarse tanto en Python 2 como en Python 3, no me parece satisfactorio codificar manualmente todas las cadenas escritas como UTF-8 como sugieren otras respuestas.
En su lugar, he escrito el siguiente pequeño relleno (porque no pude encontrar algo así en seis) para envolver un objeto similar a un archivo binario en un objeto similar a un archivo UTF-8:
from __future__ import unicode_literals
import sys
import codecs
if sys.hexversion < 0x03000000:
def uwriter(fp):
return codecs.getwriter(''utf-8'')(fp)
else:
def uwriter(fp):
return fp
Se utiliza de la siguiente manera:
# encoding: utf-8
from tempfile import NamedTemporaryFile
with uwriter(NamedTemporaryFile(suffix=''.txt'', mode=''w'')) as fp:
fp.write(''Hællo wörld!/n'')
tempfile.TemporaryFile tiene la opción de codificación en Python 3 :
#!/usr/bin/python3
# -*- coding: utf-8 -*-
import tempfile
with tempfile.TemporaryFile(mode=''w+'', encoding=''utf-8'') as fh:
fh.write("Hello World: ä")
fh.seek(0)
for line in fh:
print(line)
Tenga en cuenta que ahora debe especificar el modo = ''w +'' en lugar del modo binario predeterminado. También tenga en cuenta que los literales de cadena son implícitamente Unicode en Python 3, no hay un modificador de u .
Si está atascado con Python 2.6, los archivos temporales siempre son binarios, y necesita codificar la cadena Unicode antes de escribirla en el archivo:
#!/usr/bin/python
# -*- coding: utf-8 -*-
import tempfile
with tempfile.TemporaryFile() as fh:
fh.write(u"Hello World: ä".encode(''utf-8''))
fh.seek(0)
for line in fh:
print line.decode(''utf-8'')
Unicode especifica el conjunto de caracteres, no la codificación, por lo que en cualquier caso necesita una forma de especificar cómo codificar los caracteres Unicode.