Nach diesem Python-Beispiel kodiere ich einen String als Base64 mit:
>>> import base64
>>> encoded = base64.b64encode(b'data to be encoded')
>>> encoded
b'ZGF0YSB0byBiZSBlbmNvZGVk'
Wenn ich jedoch den führenden b
weglasse:
>>> encoded = base64.b64encode('data to be encoded')
Ich erhalte folgende Fehlermeldung:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "C:\Python32\lib\base64.py", line 56, in b64encode
raise TypeError("expected bytes, not %s" % s.__class__.__name__)
TypeError: expected bytes, not str
Warum ist das?
für die base64-Codierung werden 8-Bit-Binärbyte-Daten verwendet, und für die Codierung werden nur die Zeichen A-Z
, a-z
, 0-9
, +
, /
* verwendet, damit sie über Kanäle übertragen werden können, die nicht alle 8-Bit-Daten wie E-Mail enthalten.
Daher will es eine Zeichenfolge von 8-Bit-Bytes. Sie erstellen diese in Python 3 mit der b''
-Syntax.
Wenn Sie die Variable b
entfernen, wird daraus eine Zeichenfolge. Eine Zeichenfolge ist eine Folge von Unicode-Zeichen. base64 hat keine Ahnung, was mit Unicode-Daten zu tun ist, es ist nicht 8-Bit. Es sind eigentlich keine Bits. :-)
In Ihrem zweiten Beispiel:
>>> encoded = base64.b64encode('data to be encoded')
Alle Zeichen passen gut in den ASCII - Zeichensatz, und die Base64-Kodierung ist daher eigentlich etwas sinnlos. Sie können es stattdessen mit in ASCII konvertieren
>>> encoded = 'data to be encoded'.encode('ascii')
Oder einfacher:
>>> encoded = b'data to be encoded'
Was wäre in diesem Fall dasselbe.
* Die meisten base64-Geschmacksrichtungen können am Ende einen =
als Auffüllung enthalten. Außerdem können einige base64-Varianten andere Zeichen als +
und /
verwenden. Eine Übersicht finden Sie in der Varianten-Übersichtstabelle bei Wikipedia.
Sie müssen ein bytes-like
-Objekt (bytes
, bytearray
usw.) an die base64.b64encode()
-Methode senden. Hier gibt es zwei Möglichkeiten:
>>> data = base64.b64encode(b'data to be encoded')
>>> print(data)
b'ZGF0YSB0byBiZSBlbmNvZGVk'
Oder mit einer Variable:
>>> string = 'data to be encoded'
>>> data = base64.b64encode(string.encode())
>>> print(data)
b'ZGF0YSB0byBiZSBlbmNvZGVk'
In Python 3 sind str
-Objekte keine Zeichen-Arrays im C-Stil (also nicht - Byte-Arrays), sondern Datenstrukturen, die keine inhärente Kodierung aufweisen. Sie können diese Zeichenfolge auf verschiedene Arten kodieren (oder interpretieren). Die häufigste (und in Python 3 Standard) ist utf-8, zumal es mit ASCII abwärtskompatibel ist (obwohl, wie bei den am häufigsten verwendeten Kodierungen). Das passiert, wenn Sie eine string
nehmen und die .encode()
-Methode aufrufen: Python interpretiert die Zeichenfolge in utf-8 (die Standardcodierung) und stellt Ihnen das entsprechende Byte-Array zur Verfügung.
Ursprünglich wurde im Fragetitel nach der Base-64-Kodierung gefragt. Lesen Sie weiter für Base-64.
base64
-Codierung verwendet 6-Bit-Binärblöcke und codiert sie mit den Zeichen AZ, az, 0-9, '+', '/' und '=' (bei einigen Codierungen werden anstelle von '+' und '/' unterschiedliche Zeichen verwendet. ). Dies ist eine Zeichencodierung, die auf dem mathematischen Konstrukt des Radix-64- oder Basis-64-Zahlensystems basiert, aber sie sind sehr unterschiedlich. Base-64 ist in Mathematik ein Zahlensystem wie Binär- oder Dezimalzahl, und Sie ändern diese Basis für die gesamte Zahl oder (wenn die Basis, aus der Sie konvertieren, eine Potenz von 2 oder weniger als 64 ist) in Abschnitten von rechts nach rechts links.
Bei der Codierung base64
erfolgt die Übersetzung von links nach rechts. Diese ersten 64 Zeichen heißen base64
coding. Das 65. "=" - Symbol wird zum Auffüllen verwendet, da die Codierung 6-Bit-Chunks zieht, die Daten, die normalerweise codiert werden sollen, jedoch aus 8-Bit-Bytes bestehen, sodass im letzten Chunk manchmal nur zwei oder vier Bits vorhanden sind.
Beispiel:
>>> data = b'test'
>>> for byte in data:
... print(format(byte, '08b'), end=" ")
...
01110100 01100101 01110011 01110100
>>>
Wenn Sie diese binären Daten als eine einzelne Ganzzahl interpretieren, konvertieren Sie sie in Basis-10 und Basis-64 ( Tabelle für Basis-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
coding gruppiert diese Daten jedoch auf diese Weise neu:
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
'B0ZXN0' ist also die Basis-64-Version unserer Binärdatei, mathematisch gesehen. Allerdings muss base64
coding die Kodierung in die entgegengesetzte Richtung durchführen (die Rohdaten werden also in 'dGVzdA' konvertiert). Außerdem hat sie eine Regel, die anderen Anwendungen mitteilt, wie viel Platz am Ende übrig bleibt. Dies geschieht durch Auffüllen des Endes mit '='. Die base64
-Kodierung dieser Daten ist also 'dGVzdA ==', wobei zwei '=' - Symbole zur Kennzeichnung von zwei Bitpaaren vom Ende entfernt werden müssen, wenn diese Daten decodiert werden, damit sie mit den ursprünglichen Daten übereinstimmen.
Lassen Sie uns dies testen, um zu sehen, ob ich unehrlich bin:
>>> encoded = base64.b64encode(data)
>>> print(encoded)
b'dGVzdA=='
base64
-Codierung verwenden?Angenommen, ich muss einige Daten per E-Mail an jemanden senden, z. B. diese Daten:
>>> data = b'\x04\x6d\x73\x67\x08\x08\x08\x20\x20\x20'
>>> print(data.decode())
>>> print(data)
b'\x04msg\x08\x08\x08 '
>>>
Ich habe zwei Probleme angelegt:
\x04
gelesen wurde, da dies ASCII für END-OF-TRANSMISSION
(Ctrl-D) ist, sodass die restlichen Daten nicht berücksichtigt werden die Übertragung.BACKSPACE
-Zeichen und drei SPACE
-Zeichen verwendet habe, um die 'msg' zu löschen. Selbst wenn ich dort nicht das Zeichen EOF
hätte, könnte der Endbenutzer den Text auf dem Bildschirm nicht in die realen Rohdaten übersetzen.Dies ist nur eine Demo, die Ihnen zeigt, wie schwierig es sein kann, Rohdaten einfach zu senden. Durch die Kodierung der Daten im base64-Format erhalten Sie exakt dieselben Daten, jedoch in einem Format, das sicher für das Senden über elektronische Medien wie E-Mail ist.
Wenn die zu codierenden Daten "exotische" Zeichen enthalten, denke ich, dass Sie in "UTF-8" codieren müssen.
encoded = base64.b64encode (bytes('data to be encoded', "utf-8"))
Wenn der String Unicode ist, ist der einfachste Weg:
import base64
a = base64.b64encode(bytes(u'complex string: ñáéíóúÑ', "utf-8"))
b = base64.b64decode(a).decode("utf-8", "ignore")
print(b)
Es gibt alles was Sie brauchen:
expected bytes, not str
Die führende Variable b
macht Ihre Zeichenfolge binär.
Welche Python-Version verwenden Sie? 2.x oder 3.x?
Edit: Siehe http://docs.python.org/release/3.0.1/whatsnew/3.0.html#text-vs-data-instead-of-unicode-vs-8-bit für die blutigen Details von Strings in Python 3.x
Dies bedeutet einfach, dass Sie die Eingabe als Byte- oder Byte-Array und nicht als Zeichenfolge verwenden.