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:
<?xml encoding="utf-8"?>
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:
>>> x = eval("'Capit\\xc3\\xa1n\\n'")
>>> x
'Capit\xc3\xa1n\n'
>>> x[5]
'\xc3'
>>> len(x[5])
1
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:
>>> x.decode('utf-8')
u'Capit\xe1n\n'
Gregg Lind perguntou: Acho que faltam algumas peças aqui: o arquivo f2 contém: hex:
0000000: 4361 7069 745c 7863 335c 7861 316e Capit\xc3\xa1n
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 uso codecs.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.