Cách sử dụng các hàm unicode () và encode () trong Python


83

Tôi gặp sự cố với việc mã hóa biến đường dẫn và chèn nó vào cơ sở dữ liệu SQLite . Tôi đã cố gắng giải quyết nó bằng hàm encode ("utf-8") nhưng không giúp được gì. Sau đó, tôi sử dụng hàm unicode () cho tôi loại unicode .

print type(path)                  # <type 'unicode'>
path = path.replace("one", "two") # <type 'str'>
path = path.encode("utf-8")       # <type 'str'> strange
path = unicode(path)              # <type 'unicode'>

Cuối cùng, tôi đã đạt được loại unicode , nhưng tôi vẫn gặp lỗi tương tự khi loại biến đường dẫnstr

sqlite3.ProgrammingError: Bạn không được sử dụng bytestrings 8 bit trừ khi bạn sử dụng text_factory có thể giải thích bytestrings 8 bit (như text_factory = str). Bạn rất nên chuyển ứng dụng của mình sang chuỗi Unicode.

Bạn có thể giúp tôi giải quyết lỗi này và giải thích cách sử dụng chính xác của encode("utf-8")và các unicode()chức năng? Tôi thường chiến đấu với nó.

BIÊN TẬP:

Câu lệnh execute () này đã gây ra lỗi:

cur.execute("update docs set path = :fullFilePath where path = :path", locals())

Tôi đã quên thay đổi mã hóa của biến fullFilePath gặp phải vấn đề tương tự, nhưng tôi đang khá bối rối. Tôi có nên chỉ sử dụng unicode () hoặc encode ("utf-8") hay cả hai không?

Tôi không thể sử dụng

fullFilePath = unicode(fullFilePath.encode("utf-8"))

vì nó làm phát sinh lỗi này:

UnicodeDecodeError: codec 'ascii' không thể giải mã byte 0xc5 ở vị trí 32: thứ tự không trong phạm vi (128)

Phiên bản Python2.7.2


đâu là mã gây ra lỗi?
newtover

2
Câu hỏi chính xác của bạn đã được trả lời: [ stackoverflow.com/questions/2392732/… [1]: stackoverflow.com/questions/2392732/…
garnertb

@newtover Tôi đã chỉnh sửa câu hỏi.
xralf

bạn đã chuyển đổi cả hai biến được sử dụng thành unicodechưa?
newtover

2
Học cách Python 3 xử lý văn bản và dữ liệu đã thực sự giúp tôi hiểu mọi thứ. Đó là sau đó dễ dàng để áp dụng kiến thức để Python 2.
Oleh Prypin

Câu trả lời:


87

Bạn đang sử dụng encode("utf-8")không đúng cách. Chuỗi byte Python ( strkiểu) có bảng mã, Unicode thì không. Bạn có thể chuyển đổi một chuỗi Unicode thành chuỗi byte Python bằng cách sử dụng uni.encode(encoding)và bạn có thể chuyển đổi một chuỗi byte thành chuỗi Unicode bằng cách sử dụng s.decode(encoding)(hoặc tương đương unicode(s, encoding)).

Nếu fullFilePathpathhiện là một strloại, bạn nên tìm ra cách chúng được mã hóa. Ví dụ: nếu mã hóa hiện tại là utf-8, bạn sẽ sử dụng:

path = path.decode('utf-8')
fullFilePath = fullFilePath.decode('utf-8')

Nếu cách này không khắc phục được, vấn đề thực sự có thể là bạn không sử dụng chuỗi Unicode trong execute()cuộc gọi của mình , hãy thử thay đổi nó thành như sau:

cur.execute(u"update docs set path = :fullFilePath where path = :path", locals())

Tuyên bố này fullFilePath = fullFilePath.decode("utf-8")vẫn phát sinh lỗi UnicodeEncodeError: 'ascii' codec can't encode characters in position 32-34: ordinal not in range(128). fullFilePath là sự kết hợp của kiểu str và chuỗi được lấy từ cột văn bản của bảng db nên được mã hóa utf-8.
xralf

Theo điều này, nhưng nó có thể là UTF-8, UTF-16BE hoặc UTF-16LE. Tôi có thể tìm ra nó bằng cách nào đó không?
xralf

@xralf, Nếu bạn đang kết hợp các strđối tượng khác nhau, bạn có thể đang trộn các mã hóa. Bạn có thể hiển thị kết quả của print repr(fullFilePath)?
Andrew Clark

Tôi chỉ có thể hiển thị nó trước lệnh gọi decode () . Các ký tự có vấn đề là \ u0161 và \ u0165.
xralf

@xralf - Vậy nó đã là unicode? Hãy thử thay đổi lệnh gọi thực thi thành unicode:cur.execute(u"update docs set path = :fullFilePath where path = :path", locals())
Andrew Clark

121

strlà biểu diễn văn bản theo byte, unicodelà biểu diễn văn bản bằng ký tự.

Bạn giải mã văn bản từ byte thành unicode và mã hóa unicode thành byte với một số mã hóa.

Đó là:

>>> 'abc'.decode('utf-8')  # str to unicode
u'abc'
>>> u'abc'.encode('utf-8') # unicode to str
'abc' 

1
Câu trả lời rất hay, đi thẳng vào vấn đề. Tôi muốn thêm rằng unicodenói về chữ hoặc biểu tượng, hoặc quát hơn: rune trong khi strđại diện cho một chuỗi byte trong một mã hóa nào đó, mà bạn phải decode(rõ ràng trong mã hóa chính xác) để có được những rune cụ
arainone

1

Đảm bảo rằng bạn đã đặt cài đặt ngôn ngữ của mình ngay trước khi chạy tập lệnh từ trình bao, ví dụ:

$ locale -a | grep "^en_.\+UTF-8"
en_GB.UTF-8
en_US.UTF-8
$ export LC_ALL=en_GB.UTF-8
$ export LANG=en_GB.UTF-8

Tài liệu: man locale, man setlocale.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.