Resposta curta
É necessário empurrar um bytes-like
objecto ( bytes
, bytearray
, etc.) para o base64.b64encode()
método. Aqui estão duas maneiras:
>>> data = base64.b64encode(b'data to be encoded')
>>> print(data)
b'ZGF0YSB0byBiZSBlbmNvZGVk'
Ou com uma variável:
>>> string = 'data to be encoded'
>>> data = base64.b64encode(string.encode())
>>> print(data)
b'ZGF0YSB0byBiZSBlbmNvZGVk'
Por quê?
Em Python 3, str
objectos não são matrizes de caracteres de estilo C (de modo que eles são não byte matrizes), mas em vez disso, eles são estruturas de dados que não têm qualquer codificação inerente. Você pode codificar essa sequência (ou interpretá-la) de várias maneiras. O mais comum (e o padrão no Python 3) é o utf-8, especialmente porque é compatível com o ASCII (embora, como as codificações mais usadas). É o que está acontecendo quando você pega um string
e chama o .encode()
método: Python está interpretando a string em utf-8 (a codificação padrão) e fornecendo a matriz de bytes a que corresponde.
Codificação Base-64 em Python 3
Originalmente, o título da pergunta era sobre a codificação Base-64. Leia sobre as coisas da Base-64.
base64
a codificação pega pedaços binários de 6 bits e os codifica usando os caracteres AZ, az, 0-9, '+', '/' e '=' (algumas codificações usam caracteres diferentes no lugar de '+' e '/') . Essa é uma codificação de caracteres baseada na construção matemática do sistema de números radix-64 ou base-64, mas eles são muito diferentes. A base-64 em matemática é um sistema numérico como binário ou decimal, e você faz essa alteração de raiz em todo o número, ou (se a raiz da qual você está convertendo for uma potência de 2 menor que 64) em pedaços da direita para esquerda.
Na base64
codificação, a tradução é feita da esquerda para a direita; esses primeiros 64 caracteres são o motivo pelo qual é chamado de base64
codificação . O 65º símbolo '=' é usado para preenchimento, pois a codificação extrai pedaços de 6 bits, mas os dados que costuma codificar são bytes de 8 bits, portanto, às vezes, existem apenas dois ou 4 bits no último pedaço.
Exemplo:
>>> data = b'test'
>>> for byte in data:
... print(format(byte, '08b'), end=" ")
...
01110100 01100101 01110011 01110100
>>>
Se você interpretar esses dados binários como um único número inteiro, é assim que você os converteria em base 10 e base 64 ( tabela para base 64 ):
base-2: 01 110100 011001 010111 001101 110100 (base-64 grouping shown)
base-10: 1952805748
base-64: B 0 Z X N 0
base64
A codificação , no entanto, agrupará novamente esses dados:
base-2: 011101 000110 010101 110011 011101 00(0000) <- pad w/zeros to make a clean 6-bit chunk
base-10: 29 6 21 51 29 0
base-64: d G V z d A
Portanto, 'B0ZXN0' é a versão base 64 do nosso binário, matematicamente falando. No entanto, a base64
codificação deve fazer a codificação na direção oposta (para que os dados brutos sejam convertidos em 'dGVzdA') e também possui uma regra para informar a outras aplicações quanto espaço resta no final. Isso é feito preenchendo o final com símbolos '='. Portanto, a base64
codificação desses dados é 'dGVzdA ==', com dois símbolos '=' para indicar que dois pares de bits precisarão ser removidos do final quando esses dados forem decodificados para que correspondam aos dados originais.
Vamos testar isso para ver se estou sendo desonesto:
>>> encoded = base64.b64encode(data)
>>> print(encoded)
b'dGVzdA=='
Por que usar base64
codificação?
Digamos que eu tenho que enviar alguns dados para alguém por email, como esses dados:
>>> data = b'\x04\x6d\x73\x67\x08\x08\x08\x20\x20\x20'
>>> print(data.decode())
>>> print(data)
b'\x04msg\x08\x08\x08 '
>>>
Existem dois problemas que plantei:
- Se eu tentasse enviar esse email no Unix, o email seria enviado assim que o
\x04
caractere fosse lido, porque é ASCII para END-OF-TRANSMISSION
(Ctrl-D), para que os dados restantes fiquem de fora da transmissão.
- Além disso, enquanto o Python é inteligente o suficiente para escapar de todos os meus caracteres de controle malignos quando imprimo os dados diretamente, quando essa string é decodificada como ASCII, você pode ver que o 'msg' não está lá. Isso porque usei três
BACKSPACE
caracteres e três SPACE
caracteres para apagar o 'msg'. Assim, mesmo se eu não tivesse o EOF
personagem, o usuário final não seria capaz de traduzir do texto na tela para os dados reais e brutos.
Esta é apenas uma demonstração para mostrar o quão difícil pode ser simplesmente enviar dados brutos. A codificação dos dados no formato base64 fornece exatamente os mesmos dados, mas em um formato que garante a segurança do envio por mídia eletrônica, como email.