Observe que codecs.open()está obsoleto no 3.x, pois open()ganha um encodingargumento.
Ignacio Vazquez-Abrams,
Há também uma terceira forma (no Python 2.x, pelo menos): `f = arquivo (nome do arquivo) '
Adam Park em
1
@ IgnacioVazquez-Abrams Existe algum link que codecs.open()está obsoleto? Não acho isso nos documentos python3
varela
1
@varela: a página de documentação do Python que você mencionou diz: "o open () integrado e o módulo io associado são a abordagem recomendada para trabalhar com arquivos de texto codificados"
Luciano Ramalho
Respostas:
82
Desde o Python 2.6, uma boa prática é usar io.open(), que também leva um encodingargumento, como o now obsolete codecs.open(). No Python 3, io.opené um alias para o open()integrado. Portanto, io.open()funciona no Python 2.6 e em todas as versões posteriores, incluindo Python 3.4. Veja os documentos: http://docs.python.org/3.4/library/io.html
Agora, para a pergunta original: ao ler texto (incluindo "texto simples", HTML, XML e JSON) em Python 2, você deve sempre usar io.open()com uma codificação explícita ou open()com uma codificação explícita em Python 3. Isso significa que você acertou decodificar Unicode ou obter um erro logo de cara, tornando-o muito mais fácil de depurar.
O "texto simples" em ASCII puro é um mito do passado distante. O texto em inglês apropriado usa aspas curvas, travessões, marcadores, € (sinais de euro) e até mesmo diérese (¨). Não seja ingênuo! (E não vamos esquecer o padrão de design da fachada!)
Como o ASCII puro não é uma opção real, open()sem uma codificação explícita só é útil para ler arquivos binários .
@ForeverWintr A resposta está bem clara aí: use io.open()para texto e open()apenas para binário. A implicação é que codecs.open()não é de todo preferido.
Bdoserror
2
@Bdoserror, há uma resposta aí, claramente, mas não é uma resposta para a pergunta que foi feita. A questão era sobre a diferença entre opene e codecs.open, especificamente, quando o último é preferível ao primeiro. Uma resposta que nem mesmo menciona codecs.opennão pode responder a essa pergunta.
ForeverWintr
3
@ForeverWintr Se o OP fez a pergunta errada (ou seja, com a suposição de que codecs.open()era correto usar), então não há uma resposta "correta" sobre quando usá-lo. A resposta é usar em seu io.open()lugar. É como se eu perguntasse "quando devo usar uma chave inglesa para cravar um prego na parede?". A resposta certa é "use um martelo".
Bdoserror,
20
Pessoalmente, eu sempre uso, a codecs.openmenos que haja uma necessidade claramente identificada de uso open**. A razão é que muitas vezes eu fui mordido por uma entrada de utf-8 furtivamente em meus programas. "Oh, eu só sei que sempre será ascii" tende a ser uma suposição que é quebrada com frequência.
Presumir 'utf-8' como a codificação padrão tende a ser uma escolha padrão mais segura em minha experiência, já que ASCII pode ser tratado como UTF-8, mas o inverso não é verdade. E, nos casos em que realmente sei que a entrada é ASCII, ainda acredito, codecs.openpois acredito firmemente que "explícito é melhor do que implícito" .
** - no Python 2.x, pois o comentário sobre a pergunta afirma no Python 3 opensubstituicodecs.open
o que eu realmente não entendo é por que openàs vezes consegue lidar muito bem com caracteres não latinos codificados em UTF-8 do conjunto Unicode, e às vezes falha miseravelmente ...
cedbeu
Isso faz sentido para mim. io.opennão leva um parâmetro de codificação do que posso ver em python 2.7.5
radtek
1
@radtek, você está certo ao dizer que isso não é documentado; entretanto (pelo menos em 2.7.12) io.openaceita encodinge newlineparâmetros e os interpreta como o Python 3 faz. Ao contrário codecs.open, um arquivo aberto com io.openaumentará TypeError: write() argument 1 must be unicode, not straté mesmo no Python 2.7 se você tentar escrever str( bytes) nele. Um arquivo aberto com codecs.opententará, em vez disso unicode, a conversão implícita para , geralmente levando a arquivos confusos UnicodeDecodeError.
jochietoch,
9
No Python 2, existem strings Unicode e bytestrings. Se você apenas usar bytestrings, poderá ler / gravar em um arquivo aberto com open()muito bem. Afinal, as strings são apenas bytes.
O problema surge quando, digamos, você tem uma string Unicode e faz o seguinte:
>>> 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)
Então aqui obviamente você codifica explicitamente sua string Unicode em utf-8 ou usa codecs.openpara fazer isso de forma transparente.
Se você sempre usa bytestrings, não há problemas:
>>> example ='Μου αρέσει Ελληνικά'>>> open('sample.txt','w').write(example)>>>
É mais complicado do que isso porque quando você concatena uma string Unicode e uma string de bytes com o +operador, você obtém uma string Unicode. Fácil de ser mordido por aquele.
Também codecs.opennão gosta de bytes com caracteres não ASCII sendo passados em:
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)
O conselho sobre strings para entrada / saída é normalmente "converta para Unicode o mais cedo possível e de volta para bytestrings o mais tarde possível". Usar codecs.openpermite que você faça o último com muita facilidade.
Apenas tome cuidado para não fornecer strings Unicode e não bytes que possam conter caracteres não ASCII.
Você pode explicar seu segundo exemplo? Parece ser idêntico ao seu primeiro exemplo, então por que o resultado seria diferente?
Chris Johnson
Observe o uso do u''no primeiro exemplo. Isso significa que criei uma string Unicode, não uma bytestring. Essa é a diferença entre os dois exemplos. No segundo exemplo, estou criando um bytestring e escrever um deles em um arquivo está ótimo. Uma string Unicode não funciona se você estiver usando caracteres fora de ASCII.
Mandible79 de
7
Quando você precisa abrir um arquivo que possui uma determinada codificação, você deve usar o codecsmódulo.
Acho que todos os arquivos de texto têm uma certa codificação, de alguma forma (:
cedbeu
5
codecs.open, suponho, é apenas um resquício da Python 2época em que o open embutido tinha uma interface muito mais simples e menos recursos. No Python 2, embutido opennão aceita um argumento de codificação, então se você quiser usar algo diferente do modo binário ou a codificação padrão, codecs.open deveria ser usado.
Em Python 2.6, o módulo io veio em ajuda para tornar as coisas um pouco mais simples. De acordo com a documentação 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.
Dito isso, o único uso que posso pensar codecs.openno cenário atual é para a compatibilidade com versões anteriores. Em todos os outros cenários (a menos que você esteja usando Python <2.6), é preferível usar io.open. Também em Python 3.xio.opené o mesmo quebuilt-in open
Nota:
Há uma diferença sintática entre codecs.opene io.opentambém.
Não só codecs.opene io.opendiferem em termos de sintaxe, eles retornam objetos do tipo diferente. Também codecs.opensempre funciona com arquivos em modo binário.
wombatonfire
4
Quando você quiser carregar um arquivo binário, use
f = io.open(filename, 'b').
Para abrir um arquivo de texto, use sempre f = io.open(filename, encoding='utf-8')com codificação explícita.
No entanto, em python 3open faz a mesma coisa io.opene pode ser usado em seu lugar.
Nota:codecs.open está planejado para se tornar obsoleto e substituído por io.openapós sua introdução no python 2.6 . Eu só o usaria se o código precisar ser compatível com versões anteriores do python. Para mais informações sobre codecs e unicode em python, veja o Unicode HOWTO .
1. Por que não consigo abrir um arquivo no modo binário com io.openou codecs.open? 2. codecs.openainda não está obsoleto, leia a discussão na página que você vinculou.
wombatonfire
Bons pontos! 1. Você pode usar qualquer um, mas eu recomendaria novamente contra codecs.open, a menos que você esteja no python 2.5 ou mais antigo. 2. Atualizei minha resposta para refletir que a suspensão de uso não ocorreu imediatamente, mas sim no futuro.
wihlke
3
Quando você está trabalhando com arquivos de texto e deseja codificação e decodificação transparentes em objetos Unicode.
codecs.open()
está obsoleto no 3.x, poisopen()
ganha umencoding
argumento.codecs.open()
está obsoleto? Não acho isso nos documentos python3Respostas:
Desde o Python 2.6, uma boa prática é usar
io.open()
, que também leva umencoding
argumento, como o now obsoletecodecs.open()
. No Python 3,io.open
é um alias para oopen()
integrado. Portanto,io.open()
funciona no Python 2.6 e em todas as versões posteriores, incluindo Python 3.4. Veja os documentos: http://docs.python.org/3.4/library/io.htmlAgora, para a pergunta original: ao ler texto (incluindo "texto simples", HTML, XML e JSON) em Python 2, você deve sempre usar
io.open()
com uma codificação explícita ouopen()
com uma codificação explícita em Python 3. Isso significa que você acertou decodificar Unicode ou obter um erro logo de cara, tornando-o muito mais fácil de depurar.O "texto simples" em ASCII puro é um mito do passado distante. O texto em inglês apropriado usa aspas curvas, travessões, marcadores, € (sinais de euro) e até mesmo diérese (¨). Não seja ingênuo! (E não vamos esquecer o padrão de design da fachada!)
Como o ASCII puro não é uma opção real,
open()
sem uma codificação explícita só é útil para ler arquivos binários .fonte
io.open()
para texto eopen()
apenas para binário. A implicação é quecodecs.open()
não é de todo preferido.open
e ecodecs.open
, especificamente, quando o último é preferível ao primeiro. Uma resposta que nem mesmo mencionacodecs.open
não pode responder a essa pergunta.codecs.open()
era correto usar), então não há uma resposta "correta" sobre quando usá-lo. A resposta é usar em seuio.open()
lugar. É como se eu perguntasse "quando devo usar uma chave inglesa para cravar um prego na parede?". A resposta certa é "use um martelo".Pessoalmente, eu sempre uso, a
codecs.open
menos que haja uma necessidade claramente identificada de usoopen
**. A razão é que muitas vezes eu fui mordido por uma entrada de utf-8 furtivamente em meus programas. "Oh, eu só sei que sempre será ascii" tende a ser uma suposição que é quebrada com frequência.Presumir 'utf-8' como a codificação padrão tende a ser uma escolha padrão mais segura em minha experiência, já que ASCII pode ser tratado como UTF-8, mas o inverso não é verdade. E, nos casos em que realmente sei que a entrada é ASCII, ainda acredito,
codecs.open
pois acredito firmemente que "explícito é melhor do que implícito" .** - no Python 2.x, pois o comentário sobre a pergunta afirma no Python 3
open
substituicodecs.open
fonte
open
às vezes consegue lidar muito bem com caracteres não latinos codificados em UTF-8 do conjunto Unicode, e às vezes falha miseravelmente ...io.open
não leva um parâmetro de codificação do que posso ver em python 2.7.5io.open
aceitaencoding
enewline
parâmetros e os interpreta como o Python 3 faz. Ao contráriocodecs.open
, um arquivo aberto comio.open
aumentaráTypeError: write() argument 1 must be unicode, not str
até mesmo no Python 2.7 se você tentar escreverstr
(bytes
) nele. Um arquivo aberto comcodecs.open
tentará, em vez dissounicode
, a conversão implícita para , geralmente levando a arquivos confusosUnicodeDecodeError
.No Python 2, existem strings Unicode e bytestrings. Se você apenas usar bytestrings, poderá ler / gravar em um arquivo aberto com
open()
muito bem. Afinal, as strings são apenas bytes.O problema surge quando, digamos, você tem uma string Unicode e faz o seguinte:
Então aqui obviamente você codifica explicitamente sua string Unicode em utf-8 ou usa
codecs.open
para fazer isso de forma transparente.Se você sempre usa bytestrings, não há problemas:
É mais complicado do que isso porque quando você concatena uma string Unicode e uma string de bytes com o
+
operador, você obtém uma string Unicode. Fácil de ser mordido por aquele.Também
codecs.open
não gosta de bytes com caracteres não ASCII sendo passados em:O conselho sobre strings para entrada / saída é normalmente "converta para Unicode o mais cedo possível e de volta para bytestrings o mais tarde possível". Usar
codecs.open
permite que você faça o último com muita facilidade.Apenas tome cuidado para não fornecer strings Unicode e não bytes que possam conter caracteres não ASCII.
fonte
u''
no primeiro exemplo. Isso significa que criei uma string Unicode, não uma bytestring. Essa é a diferença entre os dois exemplos. No segundo exemplo, estou criando um bytestring e escrever um deles em um arquivo está ótimo. Uma string Unicode não funciona se você estiver usando caracteres fora de ASCII.Quando você precisa abrir um arquivo que possui uma determinada codificação, você deve usar o
codecs
módulo.fonte
codecs.open
, suponho, é apenas um resquício daPython 2
época em que o open embutido tinha uma interface muito mais simples e menos recursos. No Python 2, embutidoopen
não aceita um argumento de codificação, então se você quiser usar algo diferente do modo binário ou a codificação padrão, codecs.open deveria ser usado.Em
Python 2.6
, o módulo io veio em ajuda para tornar as coisas um pouco mais simples. De acordo com a documentação oficialDito isso, o único uso que posso pensar
codecs.open
no cenário atual é para a compatibilidade com versões anteriores. Em todos os outros cenários (a menos que você esteja usando Python <2.6), é preferível usario.open
. Também emPython 3.x
io.open
é o mesmo quebuilt-in open
Nota:
Há uma diferença sintática entre
codecs.open
eio.open
também.codecs.open
:io.open
:fonte
codecs.open
eio.open
diferem em termos de sintaxe, eles retornam objetos do tipo diferente. Tambémcodecs.open
sempre funciona com arquivos em modo binário.Quando você quiser carregar um arquivo binário, use
f = io.open(filename, 'b')
.Para abrir um arquivo de texto, use sempre
f = io.open(filename, encoding='utf-8')
com codificação explícita.No entanto, em python 3
open
faz a mesma coisaio.open
e pode ser usado em seu lugar.fonte
io.open
oucodecs.open
? 2.codecs.open
ainda não está obsoleto, leia a discussão na página que você vinculou.Quando você está trabalhando com arquivos de texto e deseja codificação e decodificação transparentes em objetos Unicode.
fonte
Eu estava em uma situação de abrir um arquivo .asm e processar o arquivo.
Sem muita dificuldade consigo ler todo o arquivo, alguma sugestão?
fonte