Estou tendo alguma falha cerebral ao entender a leitura e gravação de texto em um arquivo (Python 2.4).
# The string, which has an a-acute in it.
ss = u'Capit\xe1n'
ss8 = ss.encode('utf8')
repr(ss), repr(ss8)
("u'Capit \ xe1n '", "' Capit \ xc3 \ xa1n '")
print ss, ss8
print >> open('f1','w'), ss8
>>> file('f1').read()
'Capit\xc3\xa1n\n'
Então, digito no Capit\xc3\xa1n
meu editor favorito, no arquivo f2.
Então:
>>> open('f1').read()
'Capit\xc3\xa1n\n'
>>> open('f2').read()
'Capit\\xc3\\xa1n\n'
>>> open('f1').read().decode('utf8')
u'Capit\xe1n\n'
>>> open('f2').read().decode('utf8')
u'Capit\\xc3\\xa1n\n'
O que não estou entendendo aqui? Claramente, há um pouco de mágica vital (ou bom senso) que estou perdendo. O que digita em arquivos de texto para obter conversões adequadas?
O que realmente não estou conseguindo entender aqui é qual é o objetivo da representação UTF-8, se você não conseguir que o Python realmente o reconheça, quando vem de fora. Talvez eu devesse apenas JSON despejar a string e usá-la, pois ela tem uma representação asciiable! Mais ao ponto, existe uma representação ASCII desse objeto Unicode que o Python reconhecerá e decodificará quando vier de um arquivo? Se sim, como faço para obtê-lo?
>>> print simplejson.dumps(ss)
'"Capit\u00e1n"'
>>> print >> file('f3','w'), simplejson.dumps(ss)
>>> simplejson.load(open('f3'))
u'Capit\xe1n'
u'\xe1'
é um ponto de código UnicodeU+00e1
que pode ser representado usando 1 ou mais bytes, dependendo da codificação de caracteres (são 2 bytes em utf-8).b'\xe1'
é um byte (um número 225), que se qualquer carta pode representar depende carácter codificação usada para o descodificar, por exemplo, éб
(U+0431
) em CP1251,с
(U+0441
) em CP866, etc.Em vez de mexer nos métodos de codificação e decodificação, acho mais fácil especificar a codificação ao abrir o arquivo. O
io
módulo (adicionado no Python 2.6) fornece umio.open
função que possui um parâmetro de codificação.Use o método aberto do
io
módulo.Depois de chamar a função read () de f, um objeto Unicode codificado é retornado.
Observe que no Python 3, a
io.open
função é um alias para aopen
função interna. A função aberta interna suporta apenas o argumento de codificação no Python 3, não no Python 2.Editar: Anteriormente, esta resposta recomendava o módulo de codecs . O módulo de codecs pode causar problemas ao misturar
read()
ereadline()
, portanto, esta resposta agora recomenda o módulo io .Use o método aberto do módulo de codecs.
Depois de chamar a função read () de f, um objeto Unicode codificado é retornado.
Se você conhece a codificação de um arquivo, o uso do pacote de codecs será muito menos confuso.
Consulte http://docs.python.org/library/codecs.html#codecs.open
fonte
open(file,'w')
nãocodecs.open(file,'w','utf-8')
resolvidocodecs.open(...)
método também está totalmente de acordo com owith open(...):
estilo, onde sewith
preocupa em fechar o arquivo depois de tudo feito? Parece funcionar de qualquer maneira.with codecs.open(...) as f:
o tempo todo.Agora tudo que você precisa no Python3 é
open(Filename, 'r', encoding='utf-8')
[Editar em 10/02/2016 para esclarecimentos solicitados]
Python3 adicionou o parâmetro de codificação à sua função aberta. As seguintes informações sobre a função aberta são coletadas aqui: https://docs.python.org/3/library/functions.html#open
Portanto, adicionando
encoding='utf-8'
como parâmetro à função open, a leitura e gravação do arquivo é feita como utf8 (que agora também é a codificação padrão de tudo o que é feito em Python).fonte
codecs.open('somefile', encoding='utf-8')
stackoverflow.com/a/147756/149428Então, eu encontrei uma solução para o que estou procurando, que é:
Existem alguns codecs incomuns que são úteis aqui. Essa leitura específica permite obter representações UTF-8 no Python, copiá-las em um arquivo ASCII e fazer com que sejam lidas no Unicode. Sob o decodificador "string-escape", as barras não serão dobradas.
Isso permite o tipo de ida e volta que eu estava imaginando.
fonte
(codecs.open(file,"r","utf-8")
e simplesmenteopen(file,"r").read().decode("utf-8")
e ambas funcionaram perfeitamente.fonte
Na verdade, isso funcionou para mim para ler um arquivo com codificação UTF-8 no Python 3.2:
fonte
Para ler uma string Unicode e depois enviar para HTML, fiz o seguinte:
Útil para servidores http com tecnologia python.
fonte
Você se deparou com o problema geral das codificações: como posso saber em que codificação está um arquivo?
Resposta: Você não pode , a menos que o formato do arquivo preveja isso. XML, por exemplo, começa com:
Este cabeçalho foi cuidadosamente escolhido para que possa ser lido, independentemente da codificação. No seu caso, não existe essa dica, portanto, nem o seu editor nem o Python têm idéia do que está acontecendo. Portanto, você deve usar o
codecs
módulo e usarcodecs.open(path,mode,encoding)
que fornece o bit ausente no Python.Quanto ao seu editor, você deve verificar se ele oferece alguma maneira de definir a codificação de um arquivo.
O objetivo do UTF-8 é ser capaz de codificar caracteres de 21 bits (Unicode) como um fluxo de dados de 8 bits (porque essa é a única coisa que todos os computadores do mundo podem suportar). Mas como a maioria dos sistemas operacionais é anterior à era Unicode, eles não têm ferramentas adequadas para anexar as informações de codificação aos arquivos no disco rígido.
A próxima edição é a representação em Python. Isso é explicado perfeitamente no comentário de heikogerlach . Você deve entender que seu console pode exibir apenas ASCII. Para exibir Unicode ou qualquer coisa> = charcode 128, ele deve usar alguns meios de escapar. No seu editor, você não deve digitar a string de exibição com escape, mas o que a string significa (nesse caso, você deve inserir o trema e salvar o arquivo).
Dito isso, você pode usar a função Python eval () para transformar uma string de escape em uma string:
Como você pode ver, a string "\ xc3" foi transformada em um único caractere. Agora é uma sequência de 8 bits, codificada em UTF-8. Para obter Unicode:
Gregg Lind perguntou: Acho que faltam algumas peças aqui: o arquivo f2 contém: hex:
codecs.open('f2','rb', 'utf-8')
, por exemplo, lê todos eles em caracteres separados (esperado) Existe alguma maneira de gravar em um arquivo em ASCII que funcione?Resposta: Isso depende do que você quer dizer. ASCII não pode representar caracteres> 127. Portanto, você precisa de alguma maneira de dizer "os próximos caracteres significam algo especial", que é o que a sequência "\ x" faz. Diz: Os próximos dois caracteres são o código de um único caractere. "\ u" faz o mesmo usando quatro caracteres para codificar Unicode até 0xFFFF (65535).
Portanto, você não pode gravar diretamente Unicode em ASCII (porque o ASCII simplesmente não contém os mesmos caracteres). Você pode escrever como escape de string (como em f2); nesse caso, o arquivo pode ser representado como ASCII. Ou você pode escrevê-lo como UTF-8; nesse caso, você precisa de um fluxo seguro de 8 bits.
Sua solução
decode('string-escape')
está funcionando, mas você deve estar ciente da quantidade de memória que usa: Três vezes a quantidade de usocodecs.open()
.Lembre-se de que um arquivo é apenas uma sequência de bytes com 8 bits. Nem os bits nem os bytes têm um significado. É você quem diz "65 significa 'A'". Desde a
\xc3\xa1
deve se tornar "à", mas o computador não tem como saber, especifique a codificação usada ao gravar o arquivo.fonte
exceto
codecs.open()
, pode-se usario.open()
para trabalhar com Python2 ou Python3 para ler / gravar arquivo unicodeexemplo
fonte
with io.open('data.txt', 'w', 'utf-8') as file:
e tenho um erro:TypeError: an integer is required
. Depois que mudei parawith io.open('data.txt', 'w', encoding='utf-8') as file:
e funcionou.Bem, seu editor de texto favorito não percebe que
\xc3\xa1
deveriam ser literais de caracteres, mas os interpreta como texto. É por isso que você obtém as barras invertidas duplas na última linha - agora é uma barra invertida realxc3
etc. no seu arquivo.Se você quiser ler e gravar arquivos codificados em Python, use melhor o módulo codecs .
Colar texto entre o terminal e os aplicativos é difícil, porque você não sabe qual programa interpretará seu texto usando qual codificação. Você pode tentar o seguinte:
Em seguida, cole essa sequência no seu editor e verifique se a armazena usando o Latin-1. Sob a suposição de que a área de transferência não deturpa a corda, a viagem de ida e volta deve funcionar.
fonte
A sequência \ x .. é algo específico do Python. Não é uma sequência universal de escape de bytes.
O modo como você realmente entra no ASCII não codificado em UTF-8 depende do seu sistema operacional e / ou do seu editor. Veja como você faz isso no Windows . Para OS X para entrar um com um acento agudo pode apenas bater option+ E, então A, e quase todos os editores de texto em OS X suporte UTF-8.
fonte
Você também pode melhorar a
open()
função original para trabalhar com arquivos Unicode, substituindo-a no lugar, usando apartial
função A beleza desta solução é que você não precisa alterar nenhum código antigo. É transparente.fonte
Eu estava tentando analisar o iCal usando o Python 2.7.9:
Mas eu estava recebendo:
e foi corrigido com apenas:
(Agora, ele pode imprimir imagens favoritas.)
fonte
Encontrei a abordagem mais simples alterando a codificação padrão de todo o script para 'UTF-8':
qualquer declaração
open
,print
ou outra, será usada apenasutf8
.Funciona pelo menos para
Python 2.7.9
.O Thx vai para https://markhneedham.com/blog/2015/05/21/python-unicodeencodeerror-ascii-codec-cant-encode-character-uxfc-in-position-11-ordinal-not-in-range128/ ( olhe o fim).
fonte