Thông báo lỗi
UnicodeEncodeError: 'latin-1' codec can't encode character u'\u2026'
in position 35: ordinal not in range(256)
dường như chỉ ra rằng một số mã ngôn ngữ Python đang cố gắng chuyển đổi ký tự \u2026
thành một chuỗi Latin-1 (ISO8859-1) và nó không thành công. Không có gì đáng ngạc nhiên, ký tự đó là U+2026 HORIZONTAL ELLIPSIS
, không có ký tự tương đương duy nhất trong ISO8859-1.
Bạn đã khắc phục sự cố bằng cách thêm truy vấn ?charset=utf8
trong lệnh gọi kết nối SQLAlchemy của bạn:
import sqlalchemy
from sqlalchemy import create_engine, MetaData, Table
db = create_engine('mysql://user:[email protected]/db?charset=utf8')
Phần Url cơ sở dữ liệu
của tài liệu SQLAlchemy cho chúng ta biết rằng một URL bắt đầu bằng mysql
cho biết phương ngữ MySQL, sử dụng mysql-python
người lái xe.
Phần sau, DBAPI tùy chỉnh đối số connect () , cho chúng tôi biết rằng các đối số truy vấn được chuyển đến DBAPI bên dưới.
Vậy, mysql-python
có chức năng gì
trình điều khiển tạo tham số {charset: 'utf8'}
? Phần Hàm và thuộc tính
trong tài liệu của họ nói về charset
thuộc tính "... Nếu có, bộ ký tự kết nối sẽ được thay đổi thành bộ ký tự này, nếu chúng không bằng nhau."
Để tìm hiểu ý nghĩa của bộ ký tự kết nối, chúng tôi chuyển sang 10.1.4. Bộ ký tự kết nối và ảnh ghép của sổ tay tham khảo MySQL 5.6. Để ngắn gọn một câu chuyện dài, MySQL có thể diễn giải các truy vấn đến dưới dạng mã hóa khác với bộ ký tự của cơ sở dữ liệu và khác với mã hóa của kết quả truy vấn được trả về.
Vì thông báo lỗi bạn đã báo cáo trông giống như một Python chứ không phải là một thông báo lỗi SQL, tôi sẽ suy đoán rằng một cái gì đó trong SQLAlchemy hoặc mysql-python đang cố chuyển đổi truy vấn thành một mã hóa kết nối mặc định của latin-1
trước khi gửi nó. Đây là những gì gây ra lỗi. Tuy nhiên, chuỗi truy vấn ?charset=utf8
trong connect()
của bạn cuộc gọi thay đổi mã hóa kết nối và U+2026 HORIZONTAL ELLIPSIS
có thể vượt qua.
Cập nhật: bạn cũng hỏi, "nếu tôi xóa tùy chọn bộ ký tự và sau đó mã hóa mô tả bằng .encode ('cp1252'), nó sẽ hoạt động tốt. Làm thế nào để một dấu chấm lửng có thể truy cập với cp1252 nhưng không phải unicode?"
mã hóa cp1252
có
một ký tự dấu chấm lửng ngang ở giá trị byte \x85
. Do đó, có thể mã hóa một chuỗi Unicode chứa U+2026 HORIZONTAL ELLIPSIS
thành cp1252 mà không bị lỗi.
Cũng nên nhớ rằng trong Python, chuỗi Unicode và chuỗi byte là hai kiểu dữ liệu khác nhau. Thật hợp lý khi suy đoán rằng MySQLdb có thể có chính sách chỉ gửi các chuỗi byte qua kết nối SQL. Do đó, nó sẽ mã hóa một truy vấn nhận được dưới dạng chuỗi Unicode thành một chuỗi byte, nhưng sẽ để lại một truy vấn nhận được dưới dạng chuỗi byte. (Đây là suy đoán, tôi chưa xem mã nguồn.)
Trong phần theo dõi mà bạn đã đăng, hai dòng cuối cùng (gần nhất với vị trí xảy ra lỗi) hiển thị tên phương thức literal
, theo sau là unicode_literal
. Điều đó có xu hướng ủng hộ lý thuyết rằng MySQLdb đang mã hóa truy vấn mà nó nhận được dưới dạng chuỗi Unicode thành chuỗi byte.
Khi bạn tự mã hóa chuỗi truy vấn, bạn bỏ qua phần MySQLdb thực hiện mã hóa này theo cách khác. Tuy nhiên, lưu ý rằng nếu bạn mã hóa chuỗi truy vấn khác với lệnh gọi của bộ ký tự kết nối MySQL, thì bạn sẽ có mã hóa không khớp và văn bản của bạn có thể sẽ bị lưu trữ sai.