Câu trả lời ngắn
Bạn cần phải đẩy một bytes-like
đối tượng ( bytes
, bytearray
, vv) để các base64.b64encode()
phương pháp. Đây là hai cách:
>>> data = base64.b64encode(b'data to be encoded')
>>> print(data)
b'ZGF0YSB0byBiZSBlbmNvZGVk'
Hoặc với một biến:
>>> string = 'data to be encoded'
>>> data = base64.b64encode(string.encode())
>>> print(data)
b'ZGF0YSB0byBiZSBlbmNvZGVk'
Tại sao?
Trong Python 3, str
các đối tượng không phải là mảng ký tự kiểu C (vì vậy chúng không phải là mảng byte), mà đúng hơn, chúng là các cấu trúc dữ liệu không có bất kỳ mã hóa vốn có nào. Bạn có thể mã hóa chuỗi đó (hoặc giải thích nó) theo nhiều cách khác nhau. Phổ biến nhất (và mặc định trong Python 3) là utf-8, đặc biệt vì nó tương thích ngược với ASCII (mặc dù, như các mã hóa được sử dụng rộng rãi nhất). Đó là những gì đang xảy ra khi bạn thực hiện string
và gọi .encode()
phương thức trên nó: Python đang diễn giải chuỗi trong utf-8 (mã hóa mặc định) và cung cấp cho bạn mảng byte tương ứng.
Mã hóa Base-64 trong Python 3
Ban đầu tiêu đề câu hỏi hỏi về mã hóa Base-64. Đọc về công cụ Base-64.
base64
mã hóa lấy các đoạn nhị phân 6 bit và mã hóa chúng bằng các ký tự AZ, az, 0-9, '+', '/' và '=' (một số mã hóa sử dụng các ký tự khác nhau thay cho '+' và '/') . Đây là một mã hóa ký tự dựa trên cấu trúc toán học của hệ thống số radix-64 hoặc base-64, nhưng chúng rất khác nhau. Base-64 trong toán học là một hệ thống số như nhị phân hoặc thập phân và bạn thực hiện thay đổi cơ số này trên toàn bộ số hoặc (nếu cơ số bạn chuyển đổi từ có công suất bằng 2 nhỏ hơn 64) trong các khối từ phải sang trái.
Trong base64
mã hóa, bản dịch được thực hiện từ trái sang phải; 64 ký tự đầu tiên là lý do tại sao nó được gọi là base64
mã hóa . Biểu tượng '=' thứ 65 được sử dụng để đệm, vì mã hóa kéo các đoạn 6 bit nhưng dữ liệu thường được mã hóa là các byte 8 bit, do đó, đôi khi chỉ có hai hoặc 4 bit ở đoạn cuối.
Thí dụ:
>>> data = b'test'
>>> for byte in data:
... print(format(byte, '08b'), end=" ")
...
01110100 01100101 01110011 01110100
>>>
Nếu bạn diễn giải dữ liệu nhị phân đó dưới dạng một số nguyên, thì đây là cách bạn sẽ chuyển đổi nó thành cơ sở 10 và cơ sở 64 ( bảng cho cơ sở 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
mã hóa , tuy nhiên, sẽ nhóm lại dữ liệu này:
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
Vì vậy, 'B0ZXN0' là phiên bản cơ sở 64 của hệ nhị phân của chúng tôi, nói một cách toán học. Tuy nhiên, base64
mã hóa phải thực hiện mã hóa theo hướng ngược lại (vì vậy dữ liệu thô được chuyển đổi thành 'dGVzdA') và cũng có một quy tắc để cho các ứng dụng khác biết cuối cùng còn bao nhiêu dung lượng. Điều này được thực hiện bằng cách đệm phần cuối bằng ký hiệu '='. Vì vậy, base64
mã hóa của dữ liệu này là 'dGVzdA ==', với hai ký hiệu '=' để biểu thị hai cặp bit sẽ cần được xóa khỏi cuối khi dữ liệu này được giải mã để làm cho nó khớp với dữ liệu gốc.
Hãy thử kiểm tra xem tôi có thiếu trung thực không:
>>> encoded = base64.b64encode(data)
>>> print(encoded)
b'dGVzdA=='
Tại sao nên sử dụng base64
mã hóa?
Giả sử tôi phải gửi một số dữ liệu cho ai đó qua email, như dữ liệu này:
>>> data = b'\x04\x6d\x73\x67\x08\x08\x08\x20\x20\x20'
>>> print(data.decode())
>>> print(data)
b'\x04msg\x08\x08\x08 '
>>>
Có hai vấn đề tôi đã trồng:
- Nếu tôi cố gửi email đó trong Unix, email sẽ gửi ngay khi
\x04
đọc ký tự, vì đó là ASCII cho END-OF-TRANSMISSION
(Ctrl-D), vì vậy dữ liệu còn lại sẽ bị loại khỏi đường truyền.
- Ngoài ra, trong khi Python đủ thông minh để thoát khỏi tất cả các ký tự điều khiển xấu xa của tôi khi tôi in trực tiếp dữ liệu, khi chuỗi đó được giải mã là ASCII, bạn có thể thấy rằng 'thông điệp' không có ở đó. Đó là bởi vì tôi đã sử dụng ba
BACKSPACE
ký tự và ba SPACE
ký tự để xóa 'thông điệp'. Do đó, ngay cả khi tôi không có EOF
ký tự ở đó, người dùng cuối sẽ không thể dịch từ văn bản trên màn hình sang dữ liệu thực, thô.
Đây chỉ là một bản demo để cho bạn thấy việc gửi dữ liệu thô khó đến mức nào. Mã hóa dữ liệu sang định dạng base64 cung cấp cho bạn cùng một dữ liệu chính xác nhưng ở định dạng đảm bảo an toàn cho việc gửi qua phương tiện điện tử như email.