Tenga en cuenta que codecs.open()está obsoleto en 3.x, ya que open()gana un encodingargumento.
Ignacio Vazquez-Abrams
También hay una tercera forma (en Python 2.x al menos): `f = file (filename) '
Adam Parkin
1
@ IgnacioVazquez-Abrams ¿Hay algún enlace codecs.open()obsoleto? No creo que esto en los documentos de python3
varela
1
@varela: la página de documentación de Python que mencionaste dice: "el open () incorporado y el módulo io asociado son el enfoque recomendado para trabajar con archivos de texto codificados"
Luciano Ramalho
Respuestas:
83
Desde Python 2.6, una buena práctica es usar io.open(), que también toma un encodingargumento, como el ahora obsoleto codecs.open(). En Python 3, io.openes un alias para el open()archivo integrado. Así que io.open()funciona en Python 2.6 y todas las versiones posteriores, incluido Python 3.4. Ver documentos: http://docs.python.org/3.4/library/io.html
Ahora, para la pregunta original: al leer texto (incluido "texto sin formato", HTML, XML y JSON) en Python 2, siempre debe usarlo io.open()con una codificación explícita o open()con una codificación explícita en Python 3. Si lo hace, significa que obtiene correctamente decodificado Unicode, o obtiene un error de inmediato, lo que facilita la depuración.
El "texto sin formato" ASCII puro es un mito del pasado distante. El texto en inglés adecuado utiliza comillas entrecruzadas, guiones en forma de em, viñetas, € (signos de euro) e incluso diéresis (¨). ¡No seas ingenuo! (¡Y no olvidemos el patrón de diseño de fachada!)
Debido a que ASCII puro no es una opción real, open()sin una codificación explícita solo es útil para leer archivos binarios .
@ForeverWintr La respuesta está bastante clara allí: se usa io.open()para texto, y open()solo para binario. La implicación es que codecs.open()no se prefiere en absoluto.
Bdoserror
2
@Bdoserror, hay una respuesta ahí, claramente, pero no es una respuesta a la pregunta que se hizo. La pregunta era sobre la diferencia entre openy codecs.open, y específicamente cuándo es preferible este último al primero. Una respuesta que ni siquiera menciona codecs.openno puede responder esa pregunta.
ForeverWintr
3
@ForeverWintr Si el OP hizo la pregunta incorrecta (es decir, con la suposición de que codecs.open()era correcto usarlo), entonces no hay una respuesta "correcta" sobre cuándo usarlo. La respuesta es usar io.open()en su lugar. Es como si preguntara "¿cuándo debo usar una llave para clavar un clavo en una pared?". La respuesta correcta es "usa un martillo".
Bdoserror
20
Personalmente, siempre uso a codecs.openmenos que haya una clara necesidad identificada de usar open**. La razón es que ha habido muchas ocasiones en las que me ha mordido que la entrada de utf-8 se cuela en mis programas. "Oh, solo sé que siempre será ascii" tiende a ser una suposición que se rompe a menudo.
Asumir 'utf-8' como la codificación predeterminada tiende a ser una opción predeterminada más segura en mi experiencia, ya que ASCII se puede tratar como UTF-8, pero lo contrario no es cierto. Y en aquellos casos en los que realmente sé que la entrada es ASCII, lo sigo haciendo, codecs.openya que creo firmemente en "lo explícito es mejor que lo implícito" .
** - en Python 2.x, como el comentario sobre la pregunta dice en Python 3 openreemplazacodecs.open
lo que realmente no entiendo es por qué a openveces puede manejar muy bien los caracteres no latinos codificados en UTF-8 del conjunto Unicode, y a veces falla
miserablemente
Esto tiene sentido para mí. io.openno toma un parámetro de codificación de lo que puedo ver en Python
2.7.5
1
@radtek, tienes razón en que esto no está documentado; sin embargo (al menos en 2.7.12) io.openacepta encodingy newlineparámetros y interpreta como Python 3 hace. A diferencia codecs.open, un archivo abierto con io.openaumentará TypeError: write() argument 1 must be unicode, not strincluso en Python 2.7 si intenta escribir str( bytes) en él. En su lugar, un archivo abierto con codecs.openintentará una conversión implícita a unicode, lo que a menudo genera confusiones UnicodeDecodeError.
jochietoch
9
En Python 2 hay cadenas unicode y cadenas de bytes. Si solo usa cadenas de bytes, puede leer / escribir en un archivo abierto con open()muy bien. Después de todo, las cadenas son solo bytes.
El problema surge cuando, digamos, tiene una cadena Unicode y hace lo siguiente:
>>> example = u'Μου αρέσει Ελληνικά'>>> open('sample.txt','w').write(example)Traceback(most recent call last):File"<stdin>", line 1,in<module>UnicodeEncodeError:'ascii' codec can't encode characters in position 0-2: ordinal not in range(128)
Así que aquí, obviamente, codifica explícitamente su cadena Unicode en utf-8 o lo usa codecs.openpara hacerlo de forma transparente.
Si solo usa cadenas de bytes, entonces no hay problemas:
>>> example ='Μου αρέσει Ελληνικά'>>> open('sample.txt','w').write(example)>>>
Se complica más que esto porque cuando concatenas una cadena unicode y una cadena de bytes con el +operador, obtienes una cadena unicode. Es fácil que te muerda ese.
Tampoco codecs.openle gusta que se pasen cadenas de bytes con caracteres no ASCII:
codecs.open('test','w', encoding='utf-8').write('Μου αρέσει')Traceback(most recent call last):File"<stdin>", line 1,in<module>File"/usr/lib/python2.7/codecs.py", line 691,in write
return self.writer.write(data)File"/usr/lib/python2.7/codecs.py", line 351,in write
data, consumed = self.encode(object, self.errors)UnicodeDecodeError:'ascii' codec can't decode byte 0xce in position 0: ordinal not in range(128)
El consejo sobre cadenas para entrada / salida es normalmente "convertir a Unicode lo antes posible y volver a cadenas de bytes lo más tarde posible". El uso le codecs.openpermite hacer esto último muy fácilmente.
Solo tenga cuidado de darle cadenas Unicode y no cadenas de bytes que pueden tener caracteres no ASCII.
¿Puede explicar su segundo ejemplo? Parece ser idéntico a su primer ejemplo, entonces, ¿por qué el resultado sería diferente?
Chris Johnson
Tenga en cuenta el uso de u''en el primer ejemplo. Esto significa que creé una cadena Unicode, no una cadena de bytes. Ésta es la diferencia entre los dos ejemplos. En el segundo ejemplo, estoy creando una cadena de bytes y escribir una de esas en un archivo está bien. Una cadena Unicode no está bien si está utilizando caracteres fuera de ASCII.
Mandible79
7
Cuando necesite abrir un archivo que tenga una determinada codificación, utilizará el codecsmódulo.
Supongo que todos los archivos de texto tienen cierta codificación, de alguna manera (:
cedbeu
5
codecs.open, supongo, es solo un remanente de los Python 2días en que el sistema abierto incorporado tenía una interfaz mucho más simple y menos capacidades. En Python 2, lo integrado openno acepta un argumento de codificación, por lo que si desea usar algo que no sea el modo binario o la codificación predeterminada, se suponía que debía usar codecs.open.
En Python 2.6, el módulo io vino en ayuda para simplificar un poco las cosas. Según la documentación oficial
Newin version 2.6.The io module provides the Python interfaces to stream handling.UnderPython2.x, this is proposed as an alternative to the
built-in file object, but inPython3.x it is the default
interface to access files and streams.
Dicho esto, el único uso que se me ocurre codecs.openen el escenario actual es la compatibilidad con versiones anteriores. En todos los demás escenarios (a menos que esté usando Python <2.6), es preferible usar io.open. También en Python 3.xio.openes lo mismo quebuilt-in open
Nota:
También hay una diferencia sintáctica entre codecs.openy io.open.
No solo codecs.openy io.opendifieren en términos de sintaxis, devuelven objetos de diferente tipo. También codecs.opensiempre funciona con archivos en modo binario.
wombatonfire
4
Cuando desee cargar un archivo binario, use
f = io.open(filename, 'b').
Para abrir un archivo de texto, utilícelo siempre f = io.open(filename, encoding='utf-8')con codificación explícita.
Sin embargo, en python 3open hace lo mismo que io.openy se puede usar en su lugar.
Nota:codecs.open está previsto que quede obsoleto y se sustituya por io.opendespués de su introducción en Python 2.6 . Solo lo usaría si el código necesita ser compatible con versiones anteriores de Python. Para obtener más información sobre códecs y Unicode en Python, consulte Unicode HOWTO .
1. ¿Por qué no puedo abrir un archivo en modo binario con io.openo codecs.open? 2. codecs.openaún no está en desuso, lea la discusión en la página a la que vinculó.
wombatonfire
¡Buenos puntos! 1. Puede utilizar cualquiera de las dos, pero le aconsejaría de nuevo que no utilice codecs.open a menos que tenga python 2.5 o una versión anterior. 2. Actualicé mi respuesta para reflejar que la desaprobación no se produjo de inmediato, sino en el futuro.
wihlke
3
Cuando trabaja con archivos de texto y desea codificación y decodificación transparente en objetos Unicode.
codecs.open()
está obsoleto en 3.x, ya queopen()
gana unencoding
argumento.codecs.open()
obsoleto? No creo que esto en los documentos de python3Respuestas:
Desde Python 2.6, una buena práctica es usar
io.open()
, que también toma unencoding
argumento, como el ahora obsoletocodecs.open()
. En Python 3,io.open
es un alias para elopen()
archivo integrado. Así queio.open()
funciona en Python 2.6 y todas las versiones posteriores, incluido Python 3.4. Ver documentos: http://docs.python.org/3.4/library/io.htmlAhora, para la pregunta original: al leer texto (incluido "texto sin formato", HTML, XML y JSON) en Python 2, siempre debe usarlo
io.open()
con una codificación explícita oopen()
con una codificación explícita en Python 3. Si lo hace, significa que obtiene correctamente decodificado Unicode, o obtiene un error de inmediato, lo que facilita la depuración.El "texto sin formato" ASCII puro es un mito del pasado distante. El texto en inglés adecuado utiliza comillas entrecruzadas, guiones en forma de em, viñetas, € (signos de euro) e incluso diéresis (¨). ¡No seas ingenuo! (¡Y no olvidemos el patrón de diseño de fachada!)
Debido a que ASCII puro no es una opción real,
open()
sin una codificación explícita solo es útil para leer archivos binarios .fuente
io.open()
para texto, yopen()
solo para binario. La implicación es quecodecs.open()
no se prefiere en absoluto.open
ycodecs.open
, y específicamente cuándo es preferible este último al primero. Una respuesta que ni siquiera mencionacodecs.open
no puede responder esa pregunta.codecs.open()
era correcto usarlo), entonces no hay una respuesta "correcta" sobre cuándo usarlo. La respuesta es usario.open()
en su lugar. Es como si preguntara "¿cuándo debo usar una llave para clavar un clavo en una pared?". La respuesta correcta es "usa un martillo".Personalmente, siempre uso a
codecs.open
menos que haya una clara necesidad identificada de usaropen
**. La razón es que ha habido muchas ocasiones en las que me ha mordido que la entrada de utf-8 se cuela en mis programas. "Oh, solo sé que siempre será ascii" tiende a ser una suposición que se rompe a menudo.Asumir 'utf-8' como la codificación predeterminada tiende a ser una opción predeterminada más segura en mi experiencia, ya que ASCII se puede tratar como UTF-8, pero lo contrario no es cierto. Y en aquellos casos en los que realmente sé que la entrada es ASCII, lo sigo haciendo,
codecs.open
ya que creo firmemente en "lo explícito es mejor que lo implícito" .** - en Python 2.x, como el comentario sobre la pregunta dice en Python 3
open
reemplazacodecs.open
fuente
open
veces puede manejar muy bien los caracteres no latinos codificados en UTF-8 del conjunto Unicode, y a veces fallaio.open
no toma un parámetro de codificación de lo que puedo ver en Pythonio.open
aceptaencoding
ynewline
parámetros y interpreta como Python 3 hace. A diferenciacodecs.open
, un archivo abierto conio.open
aumentaráTypeError: write() argument 1 must be unicode, not str
incluso en Python 2.7 si intenta escribirstr
(bytes
) en él. En su lugar, un archivo abierto concodecs.open
intentará una conversión implícita aunicode
, lo que a menudo genera confusionesUnicodeDecodeError
.En Python 2 hay cadenas unicode y cadenas de bytes. Si solo usa cadenas de bytes, puede leer / escribir en un archivo abierto con
open()
muy bien. Después de todo, las cadenas son solo bytes.El problema surge cuando, digamos, tiene una cadena Unicode y hace lo siguiente:
Así que aquí, obviamente, codifica explícitamente su cadena Unicode en utf-8 o lo usa
codecs.open
para hacerlo de forma transparente.Si solo usa cadenas de bytes, entonces no hay problemas:
Se complica más que esto porque cuando concatenas una cadena unicode y una cadena de bytes con el
+
operador, obtienes una cadena unicode. Es fácil que te muerda ese.Tampoco
codecs.open
le gusta que se pasen cadenas de bytes con caracteres no ASCII:El consejo sobre cadenas para entrada / salida es normalmente "convertir a Unicode lo antes posible y volver a cadenas de bytes lo más tarde posible". El uso le
codecs.open
permite hacer esto último muy fácilmente.Solo tenga cuidado de darle cadenas Unicode y no cadenas de bytes que pueden tener caracteres no ASCII.
fuente
u''
en el primer ejemplo. Esto significa que creé una cadena Unicode, no una cadena de bytes. Ésta es la diferencia entre los dos ejemplos. En el segundo ejemplo, estoy creando una cadena de bytes y escribir una de esas en un archivo está bien. Una cadena Unicode no está bien si está utilizando caracteres fuera de ASCII.Cuando necesite abrir un archivo que tenga una determinada codificación, utilizará el
codecs
módulo.fuente
codecs.open
, supongo, es solo un remanente de losPython 2
días en que el sistema abierto incorporado tenía una interfaz mucho más simple y menos capacidades. En Python 2, lo integradoopen
no acepta un argumento de codificación, por lo que si desea usar algo que no sea el modo binario o la codificación predeterminada, se suponía que debía usar codecs.open.En
Python 2.6
, el módulo io vino en ayuda para simplificar un poco las cosas. Según la documentación oficialDicho esto, el único uso que se me ocurre
codecs.open
en el escenario actual es la compatibilidad con versiones anteriores. En todos los demás escenarios (a menos que esté usando Python <2.6), es preferible usario.open
. También enPython 3.x
io.open
es lo mismo quebuilt-in open
Nota:
También hay una diferencia sintáctica entre
codecs.open
yio.open
.codecs.open
:io.open
:fuente
codecs.open
yio.open
difieren en términos de sintaxis, devuelven objetos de diferente tipo. Tambiéncodecs.open
siempre funciona con archivos en modo binario.Cuando desee cargar un archivo binario, use
f = io.open(filename, 'b')
.Para abrir un archivo de texto, utilícelo siempre
f = io.open(filename, encoding='utf-8')
con codificación explícita.Sin embargo, en python 3
open
hace lo mismo queio.open
y se puede usar en su lugar.fuente
io.open
ocodecs.open
? 2.codecs.open
aún no está en desuso, lea la discusión en la página a la que vinculó.Cuando trabaja con archivos de texto y desea codificación y decodificación transparente en objetos Unicode.
fuente
Estaba en una situación para abrir un archivo .asm y procesar el archivo.
Sin muchos problemas puedo leer todo el archivo, ¿alguna sugerencia?
fuente