Codificação de Caracteres em Python

PythonBeginner
Pratique Agora

Introdução

Neste laboratório, você obterá uma compreensão abrangente da codificação de caracteres em Python. Começaremos explorando a história e os conceitos fundamentais da codificação de caracteres, desde as limitações de codificações iniciais como ASCII e codificações ANSI específicas de países até o desenvolvimento e a importância do padrão Unicode e suas várias implementações como UTF-8. Você aprenderá como verificar a codificação padrão em seu ambiente Python.

Com base nesta fundação, você aprenderá técnicas práticas para trabalhar com codificação de caracteres em Python. Isso inclui o uso das funções ord() e chr() para converter entre caracteres e suas representações inteiras, e o domínio dos métodos encode() e decode() para converter entre strings e bytes. Finalmente, você aprenderá como lidar efetivamente com potenciais erros de codificação que podem surgir durante o processo de decodificação, garantindo um processamento de texto robusto e confiável em suas aplicações Python.

Este é um Lab Guiado, que fornece instruções passo a passo para ajudá-lo a aprender e praticar. Siga as instruções cuidadosamente para completar cada etapa e ganhar experiência prática. Dados históricos mostram que este é um laboratório de nível iniciante com uma taxa de conclusão de 88%. Recebeu uma taxa de avaliações positivas de 98% dos estudantes.

Explore a História e os Conceitos de Codificação de Caracteres

Nesta etapa, exploraremos a história e os conceitos fundamentais da codificação de caracteres. Compreender como os computadores representam texto é crucial para trabalhar com vários formatos de dados e idiomas.

Inicialmente, os computadores foram desenvolvidos nos Estados Unidos, levando à criação da codificação ASCII. ASCII usa um único byte para representar caracteres e inclui letras inglesas, números e símbolos, totalizando 128 caracteres.

À medida que os computadores se tornaram mais difundidos globalmente, o ASCII provou ser insuficiente para representar caracteres de outros idiomas. Isso levou ao desenvolvimento de várias codificações específicas de países, como GB2312, GBK, Big5 e Shift_JIS. Estas eram frequentemente referidas coletivamente como codificações ANSI.

Para abordar as limitações dessas codificações díspares, o padrão Unicode foi desenvolvido. O Unicode visa fornecer um código binário único para cada caractere em todos os idiomas, permitindo o manuseio consistente de texto em diferentes plataformas e idiomas. O Unicode define os códigos de caracteres, mas não como eles são armazenados.

Vários esquemas de codificação implementam o Unicode, incluindo UCS4, UTF-8, UTF-16 e UTF-32. Entre estes, o UTF-8 é amplamente utilizado devido à sua compatibilidade retroativa com o ASCII.

No Python 3, a codificação padrão é UTF-8, que permite o uso direto de caracteres de vários idiomas, incluindo caracteres acentuados e símbolos. Em versões mais antigas como Python 2, você normalmente precisaria especificar a codificação no início do seu script usando comentários como ## -*- coding: UTF-8 -*- ou ## coding=utf-8.

Você pode verificar a codificação padrão em seu ambiente Python usando o módulo sys.

Primeiro, abra o terminal integrado no WebIDE clicando em Terminal -> New Terminal.

Em seguida, inicie o interpretador interativo do Python digitando python e pressionando Enter.

python

Você deverá ver uma saída semelhante a esta:

Python 3.10.x (main, ...)
[GCC ...] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>>

Agora, importe o módulo sys e verifique a codificação padrão:

import sys
sys.getdefaultencoding()

A saída mostrará a codificação padrão, que é tipicamente utf-8 no Python 3.

>>> import sys
>>> sys.getdefaultencoding()
'utf-8'
>>>

Saia do interpretador Python digitando exit() e pressionando Enter.

exit()

Usar ord() e chr() para Converter Caracteres e Inteiros

Nesta etapa, aprenderemos como usar as funções embutidas do Python ord() e chr() para converter entre caracteres e suas representações inteiras correspondentes em Unicode.

No Python 3, strings são representadas usando Unicode. A função ord() recebe um único caractere como entrada e retorna seu valor inteiro decimal Unicode correspondente.

Vamos criar um novo arquivo Python para experimentar essas funções. No WebIDE, clique com o botão direito no diretório project no explorador de arquivos e selecione New File. Nomeie o arquivo como char_conversion.py.

Abra char_conversion.py no editor e adicione o seguinte código:

## Use ord() para obter o valor decimal Unicode de caracteres
char1 = 'a'
char2 = 'é'
char3 = ';'

print(f"O valor decimal Unicode de '{char1}' é: {ord(char1)}")
print(f"O valor decimal Unicode de '{char2}' é: {ord(char2)}")
print(f"O valor decimal Unicode de '{char3}' é: {ord(char3)}")

Salve o arquivo pressionando Ctrl + S (ou Cmd + S no macOS).

Agora, abra o terminal integrado novamente (se ele ainda não estiver aberto) e execute o script usando o comando python:

python char_conversion.py

Você deverá ver uma saída semelhante a esta:

O valor decimal Unicode de 'a' é: 97
O valor decimal Unicode de 'é' é: 233
O valor decimal Unicode de ';' é: 59

A função chr() realiza a operação inversa. Ela recebe um inteiro decimal (ou um inteiro hexadecimal) representando um ponto de código Unicode e retorna o caractere correspondente.

Vamos adicionar mais código a char_conversion.py para usar a função chr(). Anexe as seguintes linhas ao código existente:

## Use chr() para obter o caractere a partir de um valor decimal Unicode
int1 = 8364
int2 = 8482

print(f"O caractere para o valor decimal Unicode {int1} é: {chr(int1)}")
print(f"O caractere para o valor decimal Unicode {int2} é: {chr(int2)}")

## Você também pode usar valores hexadecimais com chr()
hex_int = 0x00A9 ## Hexadecimal para o caractere '©'
print(f"O caractere para o valor hexadecimal Unicode {hex(hex_int)} é: {chr(hex_int)}")

Salve o arquivo novamente.

Execute o script a partir do terminal:

python char_conversion.py

A saída agora deve incluir os resultados da função chr():

O valor decimal Unicode de 'a' é: 97
O valor decimal Unicode de 'é' é: 233
O valor decimal Unicode de ';' é: 59
O caractere para o valor decimal Unicode 8364 é: €
O caractere para o valor decimal Unicode 8482 é: ™
O caractere para o valor hexadecimal Unicode 0xa9 é: ©

Você pode se perguntar como encontrar a representação hexadecimal Unicode de um caractere. Você pode usar a função ord() para obter o valor decimal e, em seguida, a função embutida hex() para converter o valor decimal em sua representação de string hexadecimal.

Adicione o seguinte código a char_conversion.py:

## Converta um caractere para sua representação hexadecimal Unicode
char_copyright = '©'
decimal_copyright = ord(char_copyright)
hexadecimal_copyright = hex(decimal_copyright)

print(f"O valor hexadecimal Unicode de '{char_copyright}' é: {hexadecimal_copyright}")

Salve o arquivo e execute-o pela última vez:

python char_conversion.py

A saída final incluirá o valor hexadecimal para o caractere '©':

O valor decimal Unicode de 'a' é: 97
O valor decimal Unicode de 'é' é: 233
O valor decimal Unicode de ';' é: 59
O caractere para o valor decimal Unicode 8364 é: €
O caractere para o valor decimal Unicode 8482 é: ™
O caractere para o valor hexadecimal Unicode 0xa9 é: ©
O valor hexadecimal Unicode de '©' é: 0xa9

Isso demonstra como ord(), chr() e hex() podem ser usados em conjunto para trabalhar com codificações de caracteres em Python.

Converter Entre Strings e Bytes com encode() e decode()

Nesta etapa, aprenderemos como converter entre strings do Python (que são Unicode) e objetos bytes usando os métodos encode() e decode(). Isso é essencial ao lidar com dados que precisam ser transmitidos ou armazenados em um formato de codificação específico.

O método encode() é usado para converter uma string em um objeto bytes usando uma codificação especificada. Ele retorna um objeto bytes.

Vamos criar um novo arquivo Python chamado encoding_decoding.py no diretório ~/project.

Abra encoding_decoding.py no editor e adicione o seguinte código:

## Define uma string
my_string = 'café'

## Codifica a string usando UTF-8
encoded_utf8 = my_string.encode('utf-8')

## Codifica a string usando Latin-1
encoded_latin1 = my_string.encode('latin-1')

## Imprime os objetos de bytes codificados
print(f"String original: {my_string}")
print(f"Codificado em UTF-8: {encoded_utf8}")
print(f"Codificado em Latin-1: {encoded_latin1}")

Salve o arquivo.

Agora, execute o script a partir do terminal integrado:

python encoding_decoding.py

Você deverá ver uma saída mostrando a string original e sua representação em bytes tanto em UTF-8 quanto em Latin-1:

String original: café
Codificado em UTF-8: b'caf\xc3\xa9'
Codificado em Latin-1: b'caf\xe9'

Observe que a saída para os objetos de bytes começa com b', indicando que são literais de bytes. Os números hexadecimais representam as sequências de bytes para a string em cada codificação.

O método decode() é usado para converter um objeto bytes de volta para uma string usando uma codificação especificada.

Vamos adicionar código a encoding_decoding.py para decodificar os objetos bytes que criamos. Anexe as seguintes linhas ao código existente:

## Decodifica os objetos de bytes de volta para strings
decoded_utf8 = encoded_utf8.decode('utf-8')
decoded_latin1 = encoded_latin1.decode('latin-1')

## Imprime as strings decodificadas
print(f"Decodificado de UTF-8: {decoded_utf8}")
print(f"Decodificado de Latin-1: {decoded_latin1}")

Salve o arquivo.

Execute o script novamente:

python encoding_decoding.py

A saída agora mostrará a string original decodificada com sucesso tanto de bytes UTF-8 quanto de Latin-1:

String original: café
Codificado em UTF-8: b'caf\xc3\xa9'
Codificado em Latin-1: b'caf\xe9'
Decodificado de UTF-8: café
Decodificado de Latin-1: café

Isso demonstra o processo básico de codificar uma string em bytes e decodificar bytes de volta para uma string usando codificações específicas. É crucial usar a codificação correta tanto para codificar quanto para decodificar para evitar erros, o que exploraremos na próxima etapa.

Lidar com Erros de Codificação Durante a Decodificação

Nesta etapa, exploraremos o que acontece quando você tenta decodificar bytes usando a codificação incorreta e como lidar com esses erros.

Como vimos na etapa anterior, decodificar bytes com sucesso requer o conhecimento da codificação original usada para criar esses bytes. Se você tentar decodificar bytes com uma codificação incompatível, o Python gerará um erro.

Vamos modificar nosso arquivo encoding_decoding.py para demonstrar isso. Abra o arquivo no editor e adicione o seguinte código ao final:

## Tenta decodificar bytes codificados em Latin-1 usando ASCII
try:
    decoded_incorrectly = encoded_latin1.decode('ascii')
    print(f"Decodificado de Latin-1 usando ASCII: {decoded_incorrectly}")
except UnicodeDecodeError as e:
    print(f"Erro ao decodificar Latin-1 com ASCII: {e}")

Salve o arquivo.

Execute o script a partir do terminal:

python encoding_decoding.py

A saída agora incluirá a mensagem de erro ao tentar decodificar bytes Latin-1 com ASCII:

String original: café
Codificado em UTF-8: b'caf\xc3\xa9'
Codificado em Latin-1: b'caf\xe9'
Decodificado de UTF-8: café
Decodificado de Latin-1: café
Erro ao decodificar Latin-1 com ASCII: o codec 'ascii' não pode decodificar o byte 0xe9 na posição 3: ordinal não está no intervalo(128)

O UnicodeDecodeError indica que o codec ASCII encontrou bytes que não são válidos de acordo com o padrão ASCII. Neste caso, o byte 0xe9 é a representação Latin-1 de 'é', mas não é um caractere ASCII válido (ASCII cobre apenas caracteres de 0 a 127).

Ao decodificar, você também pode especificar como lidar com erros usando o parâmetro errors do método decode(). Estratégias comuns de tratamento de erros incluem:

  • 'strict' (padrão): Gera um UnicodeDecodeError.
  • 'ignore': Ignora os bytes que não podem ser decodificados.
  • 'replace': Substitui os bytes que não podem ser decodificados por um caractere de substituição (geralmente ``).
  • 'xmlcharrefreplace': Substitui os bytes que não podem ser decodificados por referências de caracteres XML.

Vamos adicionar exemplos de uso das estratégias de tratamento de erros 'ignore' e 'replace' a encoding_decoding.py. Anexe o seguinte código:

## Tenta decodificar bytes codificados em Latin-1 usando ASCII com tratamento de erros
decoded_ignore = encoded_latin1.decode('ascii', errors='ignore')
decoded_replace = encoded_latin1.decode('ascii', errors='replace')

print(f"Decodificado de Latin-1 usando ASCII (ignorar erros): {decoded_ignore}")
print(f"Decodificado de Latin-1 usando ASCII (substituir erros): {decoded_replace}")

Salve o arquivo.

Execute o script novamente:

python encoding_decoding.py

A saída agora mostrará os resultados com tratamento de erros:

String original: café
Codificado em UTF-8: b'caf\xc3\xa9'
Codificado em Latin-1: b'caf\xe9'
Decodificado de UTF-8: café
Decodificado de Latin-1: café
Erro ao decodificar Latin-1 com ASCII: o codec 'ascii' não pode decodificar o byte 0xe9 na posição 3: ordinal não está no intervalo(128)
Decodificado de Latin-1 usando ASCII (ignorar erros): caf
Decodificado de Latin-1 usando ASCII (substituir erros): caf

Como você pode ver, 'ignore' resulta em "caf" porque o byte inválido foi ignorado, removendo o caractere 'é'. 'replace' substitui o byte inválido pelo caractere de substituição ``, resultando em "caf".

A escolha da estratégia de tratamento de erros apropriada depende de suas necessidades específicas. Na maioria dos casos, é melhor usar 'strict' durante o desenvolvimento para capturar problemas de codificação precocemente. Em produção, você pode escolher 'replace' ou 'ignore' se precisar processar dados com possíveis problemas de codificação, mas esteja ciente de que isso pode levar à perda ou corrupção de dados.

Resumo

Neste laboratório, exploramos a história e os conceitos fundamentais da codificação de caracteres, começando com o ASCII e suas limitações, que levaram ao desenvolvimento de várias codificações específicas de países e, finalmente, ao padrão Unicode. Aprendemos que o Unicode fornece um código único para cada caractere e é implementado por vários esquemas de codificação como UTF-8, que é o padrão no Python 3 e é retrocompatível com ASCII. Também aprendemos como verificar a codificação padrão no Python usando o módulo sys.

Em seguida, praticamos a conversão entre caracteres e suas representações inteiras usando as funções ord() e chr(), e entre strings e bytes usando os métodos encode() e decode(). Finalmente, abordamos como lidar com possíveis erros de codificação que podem ocorrer durante o processo de decodificação.