Giá trị unicode trong python là gì?

Nó trả về một phiên bản được mã hóa utf-8 của chuỗi. Trong trường hợp thất bại, nó sẽ đưa ra một ngoại lệ UnicodeDecodeError

Tuy nhiên, phải mất hai tham số

  • mã hóa - loại mã hóa mà một chuỗi phải được mã hóa thành
  • lỗi - phản hồi khi mã hóa không thành công. Có sáu loại phản hồi lỗi
    • nghiêm ngặt - phản hồi mặc định làm tăng ngoại lệ UnicodeDecodeError khi thất bại
    • bỏ qua - bỏ qua unicode không thể mã hóa từ kết quả
    • thay thế - thay thế unicode không thể mã hóa thành dấu chấm hỏi?
    • xmlcharreplace - chèn tham chiếu ký tự XML thay vì unicode không mã hóa được
    • backslashreplace - chèn một chuỗi thoát \uNNNN thay vì unicode không mã hóa được
    • namereplace - chèn \N{. } chuỗi thoát thay vì unicode không thể mã hóa

ví dụ 1. Mã hóa thành mã hóa Utf-8 mặc định

# unicode string
string = 'pythön!'

# print string
print('The string is:', string)

# default encoding to utf-8

string_utf = string.encode()

# print result print('The encoded version is:', string_utf)

đầu ra

The string is: pythön!
The encoded version is: b'pyth\xc3\xb6n!'

ví dụ 2. Mã hóa với tham số lỗi

# unicode string
string = 'pythön!'

# print string
print('The string is:', string)

# ignore error

print('The encoded version (with ignore) is:', string.encode("ascii", "ignore"))

# replace error

print('The encoded version (with replace) is:', string.encode("ascii", "replace"))

đầu ra

The string is: pythön!
The encoded version (with ignore) is: b'pythn!'
The encoded version (with replace) is: b'pyth?n!'

Ghi chú. Hãy thử các tham số lỗi và mã hóa khác nhau


mã hóa chuỗi

Kể từ Python 3. 0, các chuỗi được lưu dưới dạng Unicode, tôi. e. mỗi ký tự trong chuỗi được biểu thị bằng một điểm mã. Vì vậy, mỗi chuỗi chỉ là một chuỗi các điểm mã Unicode

Để lưu trữ hiệu quả các chuỗi này, chuỗi các điểm mã được chuyển đổi thành một tập hợp các byte. Quá trình này được gọi là mã hóa

Có nhiều mã hóa khác nhau xử lý một chuỗi khác nhau. Các mã hóa phổ biến là utf-8, ascii, v.v.

Sử dụng phương thức chuỗi encode(), bạn có thể chuyển đổi chuỗi unicode thành bất kỳ. Theo mặc định, Python sử dụng mã hóa utf-8

HOWTO này thảo luận về hỗ trợ Unicode của Python và giải thích các vấn đề khác nhau mà mọi người thường gặp phải khi cố gắng làm việc với Unicode

Giới thiệu về Unicode

Lịch sử mã ký tự

Năm 1968, Bộ luật Tiêu chuẩn Hoa Kỳ về Trao đổi Thông tin, được biết đến nhiều hơn với tên viết tắt ASCII, đã được chuẩn hóa. ASCII mã số được xác định cho các ký tự khác nhau, với các giá trị số chạy từ 0 đến 127. Ví dụ: chữ thường 'a' được gán 97 làm giá trị mã của nó

ASCII là một tiêu chuẩn do Mỹ phát triển, vì vậy nó chỉ xác định các ký tự không có dấu. Có một chữ 'e', ​​nhưng không có 'é' hay 'Í'. Điều này có nghĩa là các ngôn ngữ yêu cầu các ký tự có dấu không thể được thể hiện trung thực trong ASCII. (Trên thực tế, các trọng âm bị thiếu cũng quan trọng đối với tiếng Anh, trong đó có các từ như 'naïve' và 'café', và một số ấn phẩm có kiểu nhà yêu cầu cách viết như 'coöperate'. )

Trong một thời gian, mọi người chỉ viết các chương trình không hiển thị dấu. Tôi nhớ đã xem Apple ][ Các chương trình CƠ BẢN, được xuất bản trên các ấn phẩm tiếng Pháp vào giữa những năm 1980, có những dòng như thế này

PRINT "FICHIER EST COMPLETE."
PRINT "CARACTERE NON ACCEPTE."

Những tin nhắn đó phải có dấu, và chúng sẽ gây nhầm lẫn cho người có thể đọc tiếng Pháp

Vào những năm 1980, hầu hết tất cả các máy tính cá nhân đều là 8 bit, nghĩa là các byte có thể chứa các giá trị nằm trong khoảng từ 0 đến 255. Mã ASCII chỉ lên tới 127, vì vậy một số máy đã gán giá trị từ 128 đến 255 cho các ký tự có dấu. Tuy nhiên, các máy khác nhau có mã khác nhau, dẫn đến sự cố khi trao đổi tệp. Cuối cùng, các bộ giá trị thường được sử dụng khác nhau cho phạm vi 128-255 đã xuất hiện. Một số là các tiêu chuẩn thực sự, được xác định bởi Tổ chức Tiêu chuẩn Quốc tế, và một số là các quy ước thực tế do công ty này hay công ty khác phát minh ra và được quản lý để bắt kịp.

255 ký tự không nhiều lắm. Ví dụ: bạn không thể khớp cả ký tự có dấu được sử dụng ở Tây Âu và bảng chữ cái Cyrillic được sử dụng cho tiếng Nga vào phạm vi 128-255 vì có hơn 127 ký tự như vậy

Bạn có thể viết các tệp bằng các mã khác nhau (tất cả các tệp tiếng Nga của bạn trong hệ thống mã hóa có tên KOI8, tất cả các tệp tiếng Pháp của bạn trong một hệ thống mã hóa khác có tên là Latin1), nhưng nếu bạn muốn viết một tài liệu tiếng Pháp trích dẫn một số văn bản tiếng Nga thì sao?

Unicode bắt đầu sử dụng ký tự 16-bit thay vì ký tự 8-bit. 16 bit có nghĩa là bạn có sẵn 2^16 = 65.536 giá trị riêng biệt, giúp có thể biểu thị nhiều ký tự khác nhau từ nhiều bảng chữ cái khác nhau; . Hóa ra là thậm chí 16 bit cũng không đủ để đáp ứng mục tiêu đó và đặc tả Unicode hiện đại sử dụng nhiều loại mã hơn, 0-1,114,111 (0x10ffff trong cơ số 16)

Có một tiêu chuẩn ISO liên quan, ISO 10646. Unicode và ISO 10646 ban đầu là những nỗ lực riêng biệt, nhưng các thông số kỹ thuật đã được hợp nhất với 1. 1 phiên bản Unicode

(Cuộc thảo luận về lịch sử của Unicode này được đơn giản hóa rất nhiều. Tôi không nghĩ rằng một lập trình viên Python trung bình cần phải lo lắng về các chi tiết lịch sử; . )

Các định nghĩa

Một ký tự là thành phần nhỏ nhất có thể có của một văn bản. 'A', 'B', 'C', v.v. , đều là các ký tự khác nhau. 'È' và 'Í' cũng vậy. Các ký tự là những thứ trừu tượng và khác nhau tùy thuộc vào ngôn ngữ hoặc ngữ cảnh mà bạn đang nói đến. Ví dụ: ký hiệu cho ôm (Ω) thường được vẽ giống như chữ in hoa omega (Ω) trong bảng chữ cái Hy Lạp (thậm chí chúng có thể giống nhau ở một số phông chữ), nhưng đây là hai ký tự khác nhau có ý nghĩa khác nhau

Tiêu chuẩn Unicode mô tả cách các ký tự được biểu thị bằng các điểm mã. Điểm mã là một giá trị số nguyên, thường được biểu thị bằng cơ số 16. Trong tiêu chuẩn, một điểm mã được viết bằng ký hiệu U+12ca để chỉ ký tự có giá trị 0x12ca (4810 thập phân). Tiêu chuẩn Unicode chứa rất nhiều bảng liệt kê các ký tự và điểm mã tương ứng của chúng

0061    'a'; LATIN SMALL LETTER A
0062    'b'; LATIN SMALL LETTER B
0063    'c'; LATIN SMALL LETTER C
...
007B    '{'; LEFT CURLY BRACKET

Nghiêm túc mà nói, những định nghĩa này ngụ ý rằng thật vô nghĩa khi nói 'đây là ký tự U+12ca'. U+12ca là một điểm mã, đại diện cho một số ký tự cụ thể; . Trong bối cảnh không chính thức, sự khác biệt này giữa các điểm mã và ký tự đôi khi sẽ bị lãng quên

Một ký tự được thể hiện trên màn hình hoặc trên giấy bằng một tập hợp các thành phần đồ họa được gọi là glyph. Ví dụ, nét chữ cho chữ hoa A là hai nét chéo và một nét ngang, mặc dù các chi tiết chính xác sẽ phụ thuộc vào phông chữ được sử dụng. Hầu hết các mã Python không cần phải lo lắng về glyphs;

mã hóa

Để tóm tắt phần trước. một chuỗi Unicode là một chuỗi các điểm mã, là các số từ 0 đến 0x10ffff. Trình tự này cần được biểu diễn dưới dạng một tập hợp các byte (nghĩa là các giá trị từ 0-255) trong bộ nhớ. Các quy tắc để dịch một chuỗi Unicode thành một chuỗi byte được gọi là mã hóa

Mã hóa đầu tiên bạn có thể nghĩ đến là một mảng các số nguyên 32 bit. Trong biểu diễn này, chuỗi “Python” sẽ trông như thế này

   P           y           t           h           o           n
0x50 00 00 00 79 00 00 00 74 00 00 00 68 00 00 00 6f 00 00 00 6e 00 00 00
   0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21 22 23

Biểu diễn này rất đơn giản nhưng sử dụng nó gây ra một số vấn đề

  1. Nó không di động;
  2. Rất lãng phí không gian. Trong hầu hết các văn bản, phần lớn các điểm mã nhỏ hơn 127 hoặc nhỏ hơn 255, do đó, rất nhiều không gian bị chiếm bởi byte 0. Chuỗi trên chiếm 24 byte so với 6 byte cần thiết cho biểu diễn ASCII. Việc tăng mức sử dụng RAM không quá quan trọng (máy tính để bàn có RAM hàng megabyte và các chuỗi thường không lớn như vậy), nhưng việc mở rộng mức sử dụng băng thông mạng và đĩa của chúng tôi lên hệ số 4 là không thể chấp nhận được
  3. Nó không tương thích với các hàm C hiện có như strlen() , vì vậy cần phải sử dụng một nhóm hàm chuỗi rộng mới.
  4. Nhiều tiêu chuẩn Internet được xác định dưới dạng dữ liệu văn bản và không thể xử lý nội dung có byte 0 được nhúng

Nói chung mọi người không dùng bảng mã này mà chọn những bảng mã khác hiệu quả và tiện lợi hơn

Mã hóa không phải xử lý mọi ký tự Unicode có thể có và hầu hết các mã hóa không. Ví dụ: mã hóa mặc định của Python là mã hóa 'ascii'. Các quy tắc để chuyển đổi một chuỗi Unicode thành bảng mã ASCII rất đơn giản;

  1. Nếu điểm mã < 128, mỗi byte giống với giá trị của điểm mã
  2. Nếu điểm mã là 128 hoặc cao hơn, thì chuỗi Unicode không thể được biểu thị trong bảng mã này. (Python đưa ra một ngoại lệ trong trường hợp này. )

Latin-1, còn được gọi là ISO-8859-1, là một mã hóa tương tự. Các điểm mã Unicode 0-255 giống hệt với các giá trị Latin-1, do đó, việc chuyển đổi sang bảng mã này chỉ cần chuyển đổi các điểm mã thành giá trị byte;

Mã hóa không phải là ánh xạ một đối một đơn giản như Latin-1. Hãy xem xét EBCDIC của IBM, được sử dụng trên các máy tính lớn của IBM. Các giá trị chữ cái không nằm trong một khối. 'a' đến 'i' có giá trị từ 129 đến 137, nhưng 'j' đến 'r' là 145 đến 153. Nếu bạn muốn sử dụng EBCDIC làm mã hóa, có thể bạn sẽ sử dụng một số loại bảng tra cứu để thực hiện chuyển đổi, nhưng đây phần lớn là chi tiết nội bộ

UTF-8 là một trong những bảng mã được sử dụng phổ biến nhất. UTF là viết tắt của "Định dạng chuyển đổi Unicode" và '8' có nghĩa là các số 8 bit được sử dụng trong mã hóa. (Cũng có mã hóa UTF-16, nhưng nó ít được sử dụng hơn UTF-8. ) UTF-8 sử dụng các quy tắc sau

  1. Nếu điểm mã <128, thì nó được biểu thị bằng giá trị byte tương ứng
  2. Nếu điểm mã nằm trong khoảng từ 128 đến 0x7ff, thì nó sẽ chuyển thành hai giá trị byte trong khoảng từ 128 đến 255
  3. Các điểm mã >0x7ff được chuyển thành chuỗi ba hoặc bốn byte, trong đó mỗi byte của chuỗi nằm trong khoảng từ 128 đến 255

UTF-8 có một số thuộc tính tiện lợi

  1. Nó có thể xử lý bất kỳ điểm mã Unicode nào
  2. Chuỗi Unicode được chuyển thành chuỗi byte không chứa byte 0 được nhúng. Điều này tránh được các vấn đề về thứ tự byte và có nghĩa là các chuỗi UTF-8 có thể được xử lý bởi các hàm C như strcpy() và được gửi qua các giao thức không thể .
  3. Một chuỗi văn bản ASCII cũng là văn bản UTF-8 hợp lệ
  4. UTF-8 khá nhỏ gọn;
  5. Nếu byte bị hỏng hoặc bị mất, có thể xác định điểm bắt đầu của điểm mã được mã hóa UTF-8 tiếp theo và đồng bộ hóa lại. Cũng không chắc rằng dữ liệu 8-bit ngẫu nhiên sẽ giống như UTF-8 hợp lệ

Người giới thiệu

The Unicode Consortium site at has character charts, a glossary, and PDF versions of the Unicode specification. Be prepared for some difficult reading. is a chronology of the origin and development of Unicode.

To help understand the standard, Jukka Korpela has written an introductory guide to reading the Unicode character tables, available at .

Another good introductory article was written by Joel Spolsky . If this introduction didn’t make things clear to you, you should try reading this alternate article before continuing.

Wikipedia entries are often helpful; see the entries for “character encoding” and UTF-8 , for example.

Hỗ trợ Unicode của Python

Bây giờ bạn đã học những kiến ​​thức cơ bản về Unicode, chúng ta có thể xem xét các tính năng Unicode của Python

Loại Unicode

Chuỗi Unicode được thể hiện dưới dạng các thể hiện của loại, một trong các loại tích hợp sẵn của Python. Nó bắt nguồn từ một loại trừu tượng được gọi là , cũng là tổ tiên của loại này; . Về cơ bản, Python đại diện cho các chuỗi Unicode dưới dạng số nguyên 16 hoặc 32 bit, tùy thuộc vào cách trình thông dịch Python được biên dịch. isinstance(value, basestring). Under the hood, Python represents Unicode strings as either 16- or 32-bit integers, depending on how the Python interpreter was compiled.

Trình tạo có chữ ký unicode(string[, encoding, errors]). All of its arguments should be 8-bit strings. The first argument is converted to Unicode using the specified encoding; if you leave off the encoding argument, the ASCII encoding is used for the conversion, so characters greater than 127 will be treated as errors:

>>> unicode('abcdef')
u'abcdef'
>>> s = unicode('abcdef')
>>> type(s)

>>> unicode('abcdef' + chr(255))
Traceback (most recent call last):
  File "", line 1, in ?
UnicodeDecodeError: 'ascii' codec can't decode byte 0xff in position 6:
                    ordinal not in range(128)

Đối số lỗi chỉ định phản hồi khi không thể chuyển đổi chuỗi đầu vào theo quy tắc mã hóa. Các giá trị pháp lý cho đối số này là 'nghiêm ngặt' (tăng ngoại lệ UnicodeDecodeError ), 'thay thế' (thêm U+FFFD, 'THỰC PHẨM THAY THẾ') hoặc . Các ví dụ sau đây cho thấy sự khác biệt.

________số 8_______

Mã hóa được chỉ định dưới dạng chuỗi chứa tên mã hóa. Trăn 2. 4 đi kèm với khoảng 100 mã hóa khác nhau; . Một số bảng mã có nhiều tên;

Chuỗi Unicode một ký tự cũng có thể được tạo bằng hàm tích hợp, lấy số nguyên và trả về chuỗi Unicode có độ dài 1 chứa điểm mã tương ứng. Thao tác ngược lại là hàm tích hợp nhận chuỗi Unicode một ký tự và trả về giá trị điểm mã

>>> unichr(40960)
u'\ua000'
>>> ord(u'\ua000')
40960

Các thể hiện của loại có nhiều phương thức giống như loại chuỗi 8 bit cho các thao tác như tìm kiếm và định dạng

>>> s = u'Was ever feather so lightly blown to and fro as this multitude?'
>>> s.count('e')
5
>>> s.find('feather')
9
>>> s.find('bird')
-1
>>> s.replace('feather', 'sand')
u'Was ever sand so lightly blown to and fro as this multitude?'
>>> s.upper()
u'WAS EVER FEATHER SO LIGHTLY BLOWN TO AND FRO AS THIS MULTITUDE?'

Lưu ý rằng đối số của các phương thức này có thể là chuỗi Unicode hoặc chuỗi 8 bit. Chuỗi 8 bit sẽ được chuyển sang Unicode trước khi thực hiện thao tác;

>>> s.find('Was\x9f')
Traceback (most recent call last):
  File "", line 1, in ?
UnicodeDecodeError: 'ascii' codec can't decode byte 0x9f in position 3: ordinal not in range(128)
>>> s.find(u'Was\x9f')
-1

Do đó, nhiều mã Python hoạt động trên chuỗi sẽ hoạt động với chuỗi Unicode mà không yêu cầu bất kỳ thay đổi nào đối với mã. (Mã đầu vào và đầu ra cần cập nhật thêm cho Unicode; sẽ nói thêm về điều này sau. )

Một phương pháp quan trọng khác là . encode([encoding], [errors='strict']) , trả về phiên bản chuỗi 8 bit của chuỗi Unicode, được mã hóa theo yêu cầu . Tham số lỗi giống với tham số của unicode() . Ví dụ sau đây cho thấy các kết quả khác nhau.

>>> u = unichr(40960) + u'abcd' + unichr(1972)
>>> u.encode('utf-8')
'\xea\x80\x80abcd\xde\xb4'
>>> u.encode('ascii')
Traceback (most recent call last):
  File "", line 1, in ?
UnicodeEncodeError: 'ascii' codec can't encode character '\ua000' in position 0: ordinal not in range(128)
>>> u.encode('ascii', 'ignore')
'abcd'
>>> u.encode('ascii', 'replace')
'?abcd?'
>>> u.encode('ascii', 'xmlcharrefreplace')
'ꀀabcd޴'

Chuỗi 8 bit của Python có . decode([encoding], [errors]) phương thức diễn giải chuỗi bằng mã hóa đã cho.

>>> u = unichr(40960) + u'abcd' + unichr(1972)   # Assemble a string
>>> utf8_version = u.encode('utf-8')             # Encode as UTF-8
>>> type(utf8_version), utf8_version
(, '\xea\x80\x80abcd\xde\xb4')
>>> u2 = utf8_version.decode('utf-8')            # Decode using UTF-8
>>> u == u2                                      # The two strings match
True

Các quy trình cấp thấp để đăng ký và truy cập các mã hóa có sẵn được tìm thấy trong mô-đun. Tuy nhiên, các chức năng mã hóa và giải mã được trả về bởi mô-đun này thường ở mức thấp hơn là thoải mái, vì vậy tôi sẽ không mô tả mô-đun ở đây. Nếu bạn cần triển khai mã hóa hoàn toàn mới, bạn sẽ cần tìm hiểu về các giao diện mô-đun, nhưng việc triển khai mã hóa là một nhiệm vụ chuyên biệt cũng sẽ không được đề cập ở đây. Tham khảo tài liệu Python để tìm hiểu thêm về mô-đun này

Phần được sử dụng phổ biến nhất của mô-đun là chức năng sẽ được thảo luận trong phần về đầu vào và đầu ra

Chữ Unicode trong mã nguồn Python

Trong mã nguồn Python, các ký tự Unicode được viết dưới dạng các chuỗi có tiền tố là ký tự 'u' hoặc 'U'. u'abcdefghijk' . Các điểm mã cụ thể có thể được viết bằng cách sử dụng trình tự thoát \u , theo sau là bốn chữ số thập lục phân cho điểm mã. Trình tự thoát \U tương tự, nhưng yêu cầu 8 chữ số hex, không phải 4.

Chữ Unicode cũng có thể sử dụng các chuỗi thoát giống như chuỗi 8 bit, bao gồm \x , nhưng \x only takes two hex digits so it can’t express an arbitrary code point. Octal escapes can go up to U+01ff, which is octal 777.

0061    'a'; LATIN SMALL LETTER A
0062    'b'; LATIN SMALL LETTER B
0063    'c'; LATIN SMALL LETTER C
...
007B    '{'; LEFT CURLY BRACKET
0

Sử dụng chuỗi thoát cho các điểm mã lớn hơn 127 là tốt với liều lượng nhỏ, nhưng sẽ gây khó chịu nếu bạn đang sử dụng nhiều ký tự có dấu, giống như trong một chương trình có thông báo bằng tiếng Pháp hoặc một số ngôn ngữ sử dụng dấu khác. Bạn cũng có thể tập hợp các chuỗi bằng hàm có sẵn, nhưng điều này thậm chí còn tẻ nhạt hơn

Lý tưởng nhất là bạn muốn có thể viết chữ bằng mã hóa tự nhiên của ngôn ngữ của mình. Sau đó, bạn có thể chỉnh sửa mã nguồn Python bằng trình chỉnh sửa yêu thích của mình, trình chỉnh sửa này sẽ hiển thị các ký tự có dấu một cách tự nhiên và có các ký tự phù hợp được sử dụng trong thời gian chạy

Python hỗ trợ viết các ký tự Unicode trong bất kỳ mã hóa nào, nhưng bạn phải khai báo mã hóa đang được sử dụng. Điều này được thực hiện bằng cách bao gồm một nhận xét đặc biệt ở dòng đầu tiên hoặc dòng thứ hai của tệp nguồn

0061    'a'; LATIN SMALL LETTER A
0062    'b'; LATIN SMALL LETTER B
0063    'c'; LATIN SMALL LETTER C
...
007B    '{'; LEFT CURLY BRACKET
1

Cú pháp được lấy cảm hứng từ ký hiệu của Emacs để chỉ định các biến cục bộ cho một tệp. Emacs hỗ trợ nhiều biến khác nhau, nhưng Python chỉ hỗ trợ 'viết mã'. Các biểu tượng -*- cho Emacs biết rằng nhận xét đó là đặc biệt; . Python tìm kiếm mã hóa. tên hoặc coding=name trong nhận xét.

Nếu bạn không bao gồm nhận xét như vậy, mã hóa mặc định được sử dụng sẽ là ASCII. Các phiên bản Python trước 2. 4 lấy châu Âu làm trung tâm và coi tiếng Latin-1 là mã hóa mặc định cho chuỗi ký tự; . 4, các ký tự lớn hơn 127 vẫn hoạt động nhưng dẫn đến cảnh báo. Ví dụ chương trình sau không có khai báo bảng mã

0061    'a'; LATIN SMALL LETTER A
0062    'b'; LATIN SMALL LETTER B
0063    'c'; LATIN SMALL LETTER C
...
007B    '{'; LEFT CURLY BRACKET
2

Khi bạn chạy nó với Python 2. 4, nó sẽ xuất ra cảnh báo sau

0061    'a'; LATIN SMALL LETTER A
0062    'b'; LATIN SMALL LETTER B
0063    'c'; LATIN SMALL LETTER C
...
007B    '{'; LEFT CURLY BRACKET
3

Thuộc tính Unicode

Đặc tả Unicode bao gồm một cơ sở dữ liệu thông tin về các điểm mã. Đối với mỗi điểm mã được xác định, thông tin bao gồm tên của ký tự, danh mục của nó, giá trị số nếu có (Unicode có các ký tự đại diện cho chữ số La Mã và phân số chẳng hạn như một phần ba và bốn phần năm). Ngoài ra còn có các thuộc tính liên quan đến việc sử dụng điểm mã trong văn bản hai chiều và các thuộc tính liên quan đến hiển thị khác

Chương trình sau hiển thị một số thông tin về một số ký tự và in giá trị số của một ký tự cụ thể

0061    'a'; LATIN SMALL LETTER A
0062    'b'; LATIN SMALL LETTER B
0063    'c'; LATIN SMALL LETTER C
...
007B    '{'; LEFT CURLY BRACKET
4

Khi chạy, bản in này

0061    'a'; LATIN SMALL LETTER A
0062    'b'; LATIN SMALL LETTER B
0063    'c'; LATIN SMALL LETTER C
...
007B    '{'; LEFT CURLY BRACKET
5

Mã danh mục là chữ viết tắt mô tả bản chất của ký tự. Chúng được nhóm thành các danh mục như “Thư”, “Số”, “Dấu chấm câu” hoặc “Ký hiệu”, các danh mục này lần lượt được chia thành các danh mục con. Để lấy mã từ đầu ra ở trên, 'Ll' có nghĩa là 'Chữ cái, chữ thường', 'Không'< . Xem <> để biết danh sách mã danh mục. means “Number, other”, 'Mn' is “Mark, nonspacing”, and 'So' is “Symbol, other”. See <> for a list of category codes.

Người giới thiệu

Các kiểu chuỗi Unicode và 8 bit được mô tả trong tài liệu tham khảo thư viện Python tại

Tài liệu về mô-đun

Tài liệu về mô-đun

Marc-André Lemburg gave a presentation at EuroPython 2002 titled “Python and Unicode”. A PDF version of his slides is available at , and is an excellent overview of the design of Python’s Unicode features.

Đọc và ghi dữ liệu Unicode

Khi bạn đã viết một số mã hoạt động với dữ liệu Unicode, vấn đề tiếp theo là đầu vào/đầu ra. Làm cách nào để bạn đưa các chuỗi Unicode vào chương trình của mình và làm cách nào để chuyển đổi Unicode thành một dạng phù hợp để lưu trữ hoặc truyền tải?

Có thể bạn không cần phải làm bất cứ điều gì tùy thuộc vào nguồn đầu vào và đích đầu ra của bạn; . Trình phân tích cú pháp XML thường trả về dữ liệu Unicode, ví dụ. Nhiều cơ sở dữ liệu quan hệ cũng hỗ trợ các cột có giá trị Unicode và có thể trả về các giá trị Unicode từ truy vấn SQL

Dữ liệu Unicode thường được chuyển đổi thành một mã hóa cụ thể trước khi được ghi vào đĩa hoặc gửi qua ổ cắm. Có thể tự mình làm tất cả công việc. mở một tệp, đọc một chuỗi 8 bit từ tệp đó và chuyển đổi chuỗi đó bằng unicode(str, encoding). However, the manual approach is not recommended.

Một vấn đề là bản chất mã hóa nhiều byte; . Nếu bạn muốn đọc tệp theo các khối có kích thước tùy ý (ví dụ: 1K hoặc 4K), bạn cần viết mã xử lý lỗi để nắm bắt trường hợp chỉ một phần của byte mã hóa một ký tự Unicode được đọc ở cuối tệp. . Một giải pháp là đọc toàn bộ tệp vào bộ nhớ và sau đó thực hiện giải mã, nhưng điều đó ngăn cản bạn làm việc với các tệp cực lớn; . (Hơn nữa, thực sự, vì trong ít nhất một lúc, bạn cần có cả chuỗi được mã hóa và phiên bản Unicode của nó trong bộ nhớ. )

Giải pháp sẽ là sử dụng giao diện giải mã cấp thấp để nắm bắt trường hợp trình tự mã hóa một phần. Công việc thực hiện điều này đã được thực hiện cho bạn. mô-đun bao gồm một phiên bản của hàm trả về một đối tượng giống như tệp giả sử nội dung của tệp ở dạng mã hóa được chỉ định và chấp nhận các tham số Unicode cho các phương thức như . read(). write() .

Các tham số của hàm là open(filename, mode='rb', encoding=None, . errors='strict', buffering=1). chế độ có thể là 'r' , 'w', or 'a', just like the corresponding parameter to the regular built-in open() function; add a '+' to update the file. đệm tương tự song song với tham số của hàm tiêu chuẩn. mã hóa là một chuỗi cung cấp mã hóa để sử dụng; . Mặt khác, một đối tượng trình bao bọc được trả về và dữ liệu được ghi hoặc đọc từ đối tượng trình bao bọc sẽ được chuyển đổi khi cần. None, a regular Python file object that accepts 8-bit strings is returned. Otherwise, a wrapper object is returned, and data written to or read from the wrapper object will be converted as needed. lỗi chỉ định hành động đối với lỗi mã hóa và có thể là một trong các giá trị thông thường của 'strict', 'ignore' và 'replace'.

Do đó, việc đọc Unicode từ một tệp rất đơn giản

0061    'a'; LATIN SMALL LETTER A
0062    'b'; LATIN SMALL LETTER B
0063    'c'; LATIN SMALL LETTER C
...
007B    '{'; LEFT CURLY BRACKET
6

Cũng có thể mở tệp ở chế độ cập nhật, cho phép đọc và ghi

0061    'a'; LATIN SMALL LETTER A
0062    'b'; LATIN SMALL LETTER B
0063    'c'; LATIN SMALL LETTER C
...
007B    '{'; LEFT CURLY BRACKET
7

Ký tự Unicode U+FEFF được sử dụng làm dấu thứ tự byte (BOM) và thường được viết dưới dạng ký tự đầu tiên của tệp để hỗ trợ tự động phát hiện thứ tự byte của tệp. Một số mã hóa, chẳng hạn như UTF-16, yêu cầu BOM xuất hiện ở đầu tệp; . Có các biến thể của các mã hóa này, chẳng hạn như 'utf-16-le' và 'utf-16-be' đối với mã hóa little-endian và big-endian, chỉ định một thứ tự byte cụ thể và không bỏ qua BOM

tên tệp Unicode

Hầu hết các hệ điều hành được sử dụng phổ biến hiện nay đều hỗ trợ tên tệp chứa các ký tự Unicode tùy ý. Thông thường, điều này được thực hiện bằng cách chuyển đổi chuỗi Unicode thành một số mã hóa khác nhau tùy thuộc vào hệ thống. Ví dụ: Mac OS X sử dụng UTF-8 trong khi Windows sử dụng mã hóa có thể định cấu hình; . Trên các hệ thống Unix, sẽ chỉ có mã hóa hệ thống tệp nếu bạn đã đặt LANG hoặc LC_CTYPE environment variables; if you haven’t, the default encoding is ASCII.

Hàm trả về mã hóa để sử dụng trên hệ thống hiện tại của bạn, trong trường hợp bạn muốn thực hiện mã hóa theo cách thủ công nhưng không có nhiều lý do để bận tâm. Khi mở một tệp để đọc hoặc ghi, thông thường bạn chỉ cần cung cấp chuỗi Unicode làm tên tệp và nó sẽ tự động được chuyển đổi sang bảng mã phù hợp với bạn

0061    'a'; LATIN SMALL LETTER A
0062    'b'; LATIN SMALL LETTER B
0063    'c'; LATIN SMALL LETTER C
...
007B    '{'; LEFT CURLY BRACKET
8

Các chức năng trong mô-đun như cũng sẽ chấp nhận tên tệp Unicode

, trả về tên tệp, gây ra sự cố. nó nên trả về phiên bản Unicode của tên tệp hay nó nên trả về các chuỗi 8 bit chứa các phiên bản được mã hóa? . Nếu bạn chuyển một chuỗi Unicode làm đường dẫn, tên tệp sẽ được giải mã bằng cách sử dụng mã hóa của hệ thống tệp và một danh sách các chuỗi Unicode sẽ được trả về, trong khi chuyển một đường dẫn 8 bit sẽ trả về các phiên bản 8 bit của tên tệp. Ví dụ: giả sử mã hóa hệ thống tệp mặc định là UTF-8, hãy chạy chương trình sau

0061    'a'; LATIN SMALL LETTER A
0062    'b'; LATIN SMALL LETTER B
0063    'c'; LATIN SMALL LETTER C
...
007B    '{'; LEFT CURLY BRACKET
9

sẽ tạo ra đầu ra sau

   P           y           t           h           o           n
0x50 00 00 00 79 00 00 00 74 00 00 00 68 00 00 00 6f 00 00 00 6e 00 00 00
   0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
0

Danh sách đầu tiên chứa tên tệp được mã hóa UTF-8 và danh sách thứ hai chứa các phiên bản Unicode

Mẹo viết chương trình nhận biết Unicode

Phần này cung cấp một số gợi ý về cách viết phần mềm xử lý Unicode

Mẹo quan trọng nhất là

Phần mềm chỉ nên hoạt động với các chuỗi Unicode bên trong, chuyển đổi sang một mã hóa cụ thể trên đầu ra

Nếu bạn cố gắng viết các hàm xử lý chấp nhận cả chuỗi Unicode và chuỗi 8 bit, bạn sẽ thấy chương trình của mình dễ bị lỗi bất cứ khi nào bạn kết hợp hai loại chuỗi khác nhau. Mã hóa mặc định của Python là ASCII, vì vậy, bất cứ khi nào một ký tự có giá trị ASCII > 127 trong dữ liệu đầu vào, bạn sẽ nhận được một vì ký tự đó không thể được xử lý bằng mã hóa ASCII

Rất dễ bỏ sót những vấn đề như vậy nếu bạn chỉ kiểm tra phần mềm của mình với dữ liệu không chứa bất kỳ dấu nào; . Do đó, mẹo thứ hai là

Bao gồm các ký tự > 127 và tốt hơn nữa là các ký tự > 255 trong dữ liệu thử nghiệm của bạn

Khi sử dụng dữ liệu đến từ trình duyệt web hoặc một số nguồn không đáng tin cậy khác, kỹ thuật phổ biến là kiểm tra các ký tự không hợp lệ trong chuỗi trước khi sử dụng chuỗi trong dòng lệnh được tạo hoặc lưu trữ chuỗi trong cơ sở dữ liệu. Nếu bạn đang làm điều này, hãy cẩn thận kiểm tra chuỗi khi nó ở dạng sẽ được sử dụng hoặc lưu trữ; . Điều này đặc biệt đúng nếu dữ liệu đầu vào cũng chỉ định mã hóa; . 'base64' that modify every single character.

Ví dụ: giả sử bạn có một hệ thống quản lý nội dung lấy tên tệp Unicode và bạn muốn không cho phép các đường dẫn có ký tự '/'. Bạn có thể viết mã này

   P           y           t           h           o           n
0x50 00 00 00 79 00 00 00 74 00 00 00 68 00 00 00 6f 00 00 00 6e 00 00 00
   0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
1

Tuy nhiên, nếu kẻ tấn công có thể chỉ định mã hóa 'base64' , thì chúng có thể vượt qua 'L2V0Yy9wYXNzd2Q . Đoạn mã trên tìm kiếm các ký tự , which is the base-64 encoded form of the string '/etc/passwd', to read a system file. The above code looks for '/' ở dạng được mã hóa và bỏ sót ký tự nguy hiểm ở dạng được giải mã.

Người giới thiệu

The PDF slides for Marc-André Lemburg’s presentation “Writing Unicode-aware Applications in Python” are available at and discuss questions of character encodings as well as how to internationalize and localize an application.

Lịch sử sửa đổi và lời cảm ơn

Cảm ơn những người sau đây đã lưu ý lỗi hoặc đưa ra đề xuất về bài viết này. Nicholas BastinMarius GedminasKent JohnsonKen KruglerMarc-André LemburgMartin von LöwisChad Whitacre

Đối tượng Unicode trong Python là gì?

Unicode trong Python . Về cơ bản, Python biểu thị các chuỗi Unicode dưới dạng số nguyên 16 hoặc 32 bit, tùy thuộc vào cách trình thông dịch Python được biên dịch. Hàm tạo unicode() có chữ ký unicode(string[, encoding, errors]). Unicode strings are expressed as instances of the built-in unicode type. Under the hood, Python represents Unicode strings as either 16 or 32 bit integers, depending on how the Python interpreter was compiled. The unicode() constructor has the signature unicode(string[, encoding, errors]) .

Giá trị Unicode của một ký tự là gì?

Unicode sử dụng hai dạng mã hóa. 8 bit và 16 bit, dựa trên loại dữ liệu của dữ liệu đang được mã hóa. Dạng mã hóa mặc định là 16 bit, trong đó mỗi ký tự rộng 16 bit (2 byte). Dạng mã hóa mười sáu bit thường được hiển thị dưới dạng U+hhhh , trong đó hhhh là điểm mã thập lục phân của ký tự.

\u trong chuỗi nghĩa là gì?

Chữ 'u' phía trước các giá trị chuỗi có nghĩa là chuỗi này là một chuỗi Unicode . Unicode là một cách để thể hiện nhiều ký tự hơn ASCII bình thường có thể quản lý.