Hướng dẫn python 2 unicode - trăn 2 unicode

Phóng thích

1.03

Điều này đã thảo luận về sự hỗ trợ của Python 2.x, và giải thích các vấn đề khác nhau mà mọi người thường gặp khi cố gắng làm việc với Unicode. Đối với phiên bản Python 3, xem.

Giới thiệu về Unicode¶

Lịch sử mã ký tự

Năm 1968, Bộ luật Trao đổi thông tin của Mỹ, được biết đến nhiều hơn bởi từ viết tắt của ASCII, đã được tiêu chuẩn hóa. ASCII đã xác định các mã số cho các ký tự khác nhau, với các giá trị số chạy từ 0 đến 127. Ví dụ, chữ cái 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 người Mỹ phát triển, vì vậy nó chỉ xác định các nhân vật không có điểm. Có một ’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 một cách trung thực trong ASCII. .

Trong một thời gian, mọi người chỉ viết các chương trình mà không hiển thị điểm nhấn. Tôi nhớ đã nhìn vào 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ư sau:

PRINT "MISE A JOUR TERMINEE"
PRINT "PARAMETRES ENREGISTRES"

Những tin nhắn đó nên chứa dấu, và chúng chỉ nhìn sai với người có thể đọc tiếng Pháp.

Trong những năm 1980, hầu hết tất cả các máy tính cá nhân là 8 bit, có nghĩa là byte có thể chứa các giá trị dao động từ 0 đến 255. Mã ASCII chỉ tăng lên 127, do đó, một số máy được 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 các vấn đề trao đổi tệp. Cuối cùng, các bộ giá trị được sử dụng phổ biến khác nhau cho phạm vi 128 128255 đã 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 hóa Quốc tế, và một số là các quy ước thực tế được phát minh bởi một công ty này hay công ty khác và quản lý để bắt kịp.

255 ký tự aren rất nhiều. Ví dụ, bạn có thể phù hợp với cả hai nhân vật có dấu được sử dụng ở Tây Âu và bảng chữ cái Cyrillic được sử dụng cho Nga vào phạm vi 128 Phản255 vì có hơn 128 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 Nga của bạn trong một hệ thống mã hóa có tên là 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 nhau có tên 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 Nga? Vào những năm 1980, mọi người bắt đầu muốn giải quyết vấn đề này và nỗ lực tiêu chuẩn hóa Unicode bắt đầu.

Unicode bắt đầu bằng cách sử dụng các ký tự 16 bit thay vì các ký tự 8 bit. 16 bit có nghĩa là bạn có 2^16 = 65,536 giá trị riêng biệt có sẵn, giúp có thể thể hiện nhiều ký tự khác nhau từ nhiều bảng chữ cái khác nhau; Mục tiêu ban đầu là có Unicode chứa bảng chữ cái cho mỗi ngôn ngữ của con người. Nó chỉ ra rằng thậm chí 16 bit là đủ để đáp ứng mục tiêu đó và đặc tả Unicode hiện đại sử dụng phạm vi mã rộng hơn, 0 Ném1.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 sửa đổi 1.1 của Unicode.

.

Định nghĩa¶

Một ký tự là thành phần nhỏ nhất có thể của một văn bản. ‘A,’ ’B,’ C, v.v., đều là những nhân vật khác nhau. Cũng vậy ’è và’ í. Các nhân vật là sự trừu tượng, và thay đổi tùy thuộc vào ngôn ngữ hoặc bối cảnh mà bạn đang nói. Ví dụ, biểu tượng cho ohms (ω) thường được vẽ giống như Omega chữ cái viết hoa () trong bảng chữ cái Hy Lạp (chúng thậm chí có thể giống nhau trong một số phông chữ), nhưng đây là hai ký tự khác nhau có ý nghĩa khác nhau.character is the smallest possible component of a text. ‘A’, ‘B’, ‘C’, etc., are all different characters. So are ‘È’ and ‘Í’. Characters are abstractions, and vary depending on the language or context you’re talking about. For example, the symbol for ohms (Ω) is usually drawn much like the capital letter omega (Ω) in the Greek alphabet (they may even be the same in some fonts), but these are two different characters that have different meanings.

Tiêu chuẩn Unicode mô tả cách các ký tự được biểu diễn bằng các điểm mã. Một điểm mã là một giá trị số nguyên, thường được biểu thị trong cơ sở 16. Trong tiêu chuẩn, một điểm mã được viết bằng ký hiệu U+12ca có nghĩa là 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à các điểm mã tương ứng của chúng:code points. A code point is an integer value, usually denoted in base 16. In the standard, a code point is written using the notation U+12ca to mean the character with value 0x12ca (4810 decimal). The Unicode standard contains a lot of tables listing characters and their corresponding code points:

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, những định nghĩa này ngụ ý rằng nó 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 trường hợp này, nó đại diện cho nhân vật ‘âm tiết ethiopic wi. Trong bối cảnh không chính thức, sự khác biệt 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ởi một tập hợp các yếu tố đồ họa mà Lọ gọi là glyph. Ví dụ, glyph cho chữ A, ví dụ, là hai nét chéo và đột quỵ 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; Tìm ra glyph chính xác để hiển thị nói chung là công việc của bộ công cụ GUI hoặc trình kết xuất phông chữ Terminal.glyph. The glyph for an uppercase A, for example, is two diagonal strokes and a horizontal stroke, though the exact details will depend on the font being used. Most Python code doesn’t need to worry about glyphs; figuring out the correct glyph to display is generally the job of a GUI toolkit or a terminal’s font renderer.

Mã hóa

Để tóm tắt phần trước: Chuỗi Unicode là chuỗi các điểm mã, là 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 (có nghĩa là các giá trị từ 0 Lỗi255) 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.encoding.

Mã hóa đầu tiên mà bạn có thể nghĩ đến là một loạt các số nguyên 32 bit. Trong đại diện này, chuỗi Py 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

Đại diện này là đơn giản nhưng sử dụng nó thể hiện một số vấn đề.

  1. Nó không di động; Các bộ xử lý khác nhau đặt hàng byte khác nhau.

  2. Nó 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 dưới 255, do đó, rất nhiều không gian bị chiếm bởi số byte bằng không. Chuỗi trên mất 24 byte so với 6 byte cần thiết cho biểu diễn ASCII. Việc sử dụng RAM tăng không quan trọng quá nhiều (máy tính để bàn có megabyte ram, và chuỗi thường không lớn), nhưng việc mở rộng việc sử dụng băng thông đĩa và mạng của chúng tôi bằng hệ số 4 là không thể chịu đựng được.

  3. Nó không tương thích với các chức năng C hiện có như

       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
    
    3, vì vậy một gia đình mới gồm các hàm chuỗi rộng sẽ cần được sử dụng.

  4. Nhiều tiêu chuẩn internet được xác định theo dữ liệu văn bản và có thể xử lý nội dung với số byte được nhúng.

Nói chung, mọi người không sử dụng mã hóa này, thay vào đó chọn các mã hóa khác hiệu quả và thuận tiện hơn. UTF-8 có lẽ là mã hóa được hỗ trợ phổ biến nhất; Nó sẽ được thảo luận dưới đây.

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

  1. Nếu điểm mã là <128, mỗi byte giống như giá trị của điểm mã.

  2. Nếu điểm mã là 128 hoặc lớn hơn, chuỗi Unicode có thể được biểu diễn trong mã hóa này. (Python tăng ngoại lệ

       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
    
    4 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 Ném255 giống hệt với các giá trị Latin-1, do đó việc chuyển đổi sang mã hóa này chỉ đơn giản yêu cầu chuyển đổi các điểm mã thành các giá trị byte; Nếu một điểm mã lớn hơn 255 gặp phải, chuỗi có thể được mã hóa thành Latin-1.

Mã hóa don lồng phải là ánh xạ một-một đơn giản như Latin-1. Hãy xem xét IBM từ EBCDIC, được sử dụng trên máy tính lớn của IBM. Giá trị chữ cái không ở trong một khối: 'A' qua 'i' có cá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 như một mã hóa, có lẽ 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à một chi tiết nội bộ.

UTF-8 là một trong những mã hóa đượ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 8 có nghĩa là các số 8 bit được sử dụng trong mã hóa. .

  1. Nếu điểm mã là

  2. Nếu điểm mã nằm trong khoảng từ 128 đến 0x7ff, thì nó đã biến thành hai giá trị byte trong khoảng từ 128 đến 255.

  3. Các điểm mã> 0x7ff được biến thành các 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 thuận tiện:

  1. Nó có thể xử lý bất kỳ điểm mã Unicode.

  2. Một chuỗi unicode được biến thành một chuỗi byte không chứa byte không nhúng. Điều này tránh các vấn đề đặt hàng 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ư

       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
    
    5 và được gửi qua các giao thức có thể xử lý số byte bằng 0.

  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; Phần lớn các điểm mã được biến thành hai byte và các giá trị dưới 128 chỉ chiếm một byte duy nhất.

  5. Nếu byte bị hỏng hoặc bị mất, thì 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. Nó cũng không chắc rằng dữ liệu 8 bit ngẫu nhiên sẽ trông giống như UTF-8 hợp lệ.

Python 2.x sườn Unicode Hỗ trợ Không

Bây giờ bạn đã học được sự thô sơ của Unicode, chúng ta có thể xem xét các tính năng của Python.

Loại unicode

Các chuỗi Unicode được biểu thị dưới dạng các trường hợp của loại

   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
6, một trong những tiết mục của Python, các loại tích hợp. Nó bắt nguồn từ một loại trừu tượng gọi là
   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
7, cũng là tổ tiên của loại
   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
8; Do đó, bạn có thể kiểm tra xem giá trị có phải là loại chuỗi có
   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
9 không. Dưới mui xe, 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 biên dịch viên python được biên dịch.

Chất xây dựng

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

>>> unicode('abcdef' + chr(255))    
Traceback (most recent call last):
...
UnicodeDecodeError: 'ascii' codec can't decode byte 0xff in position 6:
ordinal not in range(128)
0 có chữ ký
>>> unicode('abcdef')
u'abcdef'
>>> s = unicode('abcdef')
>>> type(s)

>>> unicode('abcdef' + chr(255))    
Traceback (most recent call last):
...
UnicodeDecodeError: 'ascii' codec can't decode byte 0xff in position 6:
ordinal not in range(128)
1. Tất cả các lập luận của nó phải là chuỗi 8 bit. Đối số đầu tiên được chuyển đổi thành Unicode bằng cách sử dụng mã hóa được chỉ định; Nếu bạn rời khỏi đối số
>>> unicode('abcdef')
u'abcdef'
>>> s = unicode('abcdef')
>>> type(s)

>>> unicode('abcdef' + chr(255))    
Traceback (most recent call last):
...
UnicodeDecodeError: 'ascii' codec can't decode byte 0xff in position 6:
ordinal not in range(128)
2, mã hóa ASCII được sử dụng để chuyển đổi, do đó, các ký tự lớn hơn 127 sẽ được coi là lỗi:

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

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

Đối số

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

>>> unicode('abcdef' + chr(255))    
Traceback (most recent call last):
...
UnicodeDecodeError: 'ascii' codec can't decode byte 0xff in position 6:
ordinal not in range(128)
3 chỉ định phản hồi khi chuỗi đầu vào có thể được chuyển đổi theo các 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ệ
>>> unicode('abcdef')
u'abcdef'
>>> s = unicode('abcdef')
>>> type(s)

>>> unicode('abcdef' + chr(255))    
Traceback (most recent call last):
...
UnicodeDecodeError: 'ascii' codec can't decode byte 0xff in position 6:
ordinal not in range(128)
4),‘ thay thế (thêm U+FFFD, ‘ký tự thay thế, hoặc‘ bỏ qua (chỉ cần để lại ký tự ra khỏi kết quả Unicode). Các ví dụ sau đây cho thấy sự khác biệt:

>>> unicode('\x80abc', errors='strict')     
Traceback (most recent call last):
    ...
UnicodeDecodeError: 'ascii' codec can't decode byte 0x80 in position 0:
ordinal not in range(128)
>>> unicode('\x80abc', errors='replace')
u'\ufffdabc'
>>> unicode('\x80abc', errors='ignore')
u'abc'

Mã hóa được chỉ định là các chuỗi chứa tên mã hóa. Python 2.7 đi kèm với khoảng 100 mã hóa khác nhau; Xem tham chiếu thư viện Python tại các mã hóa tiêu chuẩn để biết danh sách. Một số mã hóa có nhiều tên; Ví dụ: ‘Latin-1,‘ ISO_8859_1 và ‘8859, đều là từ đồng nghĩa với cùng một mã hóa.Standard Encodings for a list. Some encodings have multiple names; for example, ‘latin-1’, ‘iso_8859_1’ and ‘8859’ are all synonyms for the same encoding.

Các chuỗi unicode một ký tự cũng có thể được tạo với hàm tích hợp

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

>>> unicode('abcdef' + chr(255))    
Traceback (most recent call last):
...
UnicodeDecodeError: 'ascii' codec can't decode byte 0xff in position 6:
ordinal not in range(128)
5, lấy số nguyên và trả về một chuỗi unicode có độ dài 1 có chứa điểm mã tương ứng. Hoạt động ngược là hàm
>>> unicode('abcdef')
u'abcdef'
>>> s = unicode('abcdef')
>>> type(s)

>>> unicode('abcdef' + chr(255))    
Traceback (most recent call last):
...
UnicodeDecodeError: 'ascii' codec can't decode byte 0xff in position 6:
ordinal not in range(128)
6 tích hợp có 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 phiên bản của loại

   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
6 có nhiều phương pháp giống như loại chuỗi 8 bit cho các hoạt động 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 các đối số cho các phương thức này có thể là chuỗi unicode hoặc chuỗi 8 bit. Các chuỗi 8 bit sẽ được chuyển đổi thành Unicode trước khi thực hiện thao tác; Mã hóa ASCII mặc định của Python sẽ được sử dụng, do đó, các ký tự lớn hơn 127 sẽ gây ra một ngoại lệ:

>>> s.find('Was\x9f')                   
Traceback (most recent call last):
    ...
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 các chuỗi sẽ hoạt động với các 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; nhiều hơn về điều này sau.)

Một phương pháp quan trọng khác là

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

>>> unicode('abcdef' + chr(255))    
Traceback (most recent call last):
...
UnicodeDecodeError: 'ascii' codec can't decode byte 0xff in position 6:
ordinal not in range(128)
8, trả về phiên bản chuỗi 8 bit của chuỗi Unicode, được mã hóa trong mã hóa được yêu cầu. Tham số
>>> unicode('abcdef')
u'abcdef'
>>> s = unicode('abcdef')
>>> type(s)

>>> unicode('abcdef' + chr(255))    
Traceback (most recent call last):
...
UnicodeDecodeError: 'ascii' codec can't decode byte 0xff in position 6:
ordinal not in range(128)
3 giống như tham số của hàm tạo
>>> unicode('abcdef')
u'abcdef'
>>> s = unicode('abcdef')
>>> type(s)

>>> unicode('abcdef' + chr(255))    
Traceback (most recent call last):
...
UnicodeDecodeError: 'ascii' codec can't decode byte 0xff in position 6:
ordinal not in range(128)
0, với một khả năng bổ sung; Cũng như ’nghiêm ngặt,‘ bỏ qua, và ‘thay thế, bạn cũng có thể vượt qua‘ xmlcharrefreplace, sử dụng các tài liệu tham khảo ký tự XML. 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):
    ...
UnicodeEncodeError: 'ascii' codec can't encode character u'\ua000' in
position 0: ordinal not in range(128)
>>> u.encode('ascii', 'ignore')
'abcd'
>>> u.encode('ascii', 'replace')
'?abcd?'
>>> u.encode('ascii', 'xmlcharrefreplace')
'ꀀabcd޴'

Các chuỗi 8 bit Python có một phương thức

>>> unicode('\x80abc', errors='strict')     
Traceback (most recent call last):
    ...
UnicodeDecodeError: 'ascii' codec can't decode byte 0x80 in position 0:
ordinal not in range(128)
>>> unicode('\x80abc', errors='replace')
u'\ufffdabc'
>>> unicode('\x80abc', errors='ignore')
u'abc'
1 diễn giải chuỗi bằng cách sử dụ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 thói quen 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

>>> unicode('\x80abc', errors='strict')     
Traceback (most recent call last):
    ...
UnicodeDecodeError: 'ascii' codec can't decode byte 0x80 in position 0:
ordinal not in range(128)
>>> unicode('\x80abc', errors='replace')
u'\ufffdabc'
>>> unicode('\x80abc', errors='ignore')
u'abc'
2. 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
>>> unicode('\x80abc', errors='strict')     
Traceback (most recent call last):
    ...
UnicodeDecodeError: 'ascii' codec can't decode byte 0x80 in position 0:
ordinal not in range(128)
>>> unicode('\x80abc', errors='replace')
u'\ufffdabc'
>>> unicode('\x80abc', errors='ignore')
u'abc'
2 ở đây. Nếu bạn cần thực hiện 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
>>> unicode('\x80abc', errors='strict')     
Traceback (most recent call last):
    ...
UnicodeDecodeError: 'ascii' codec can't decode byte 0x80 in position 0:
ordinal not in range(128)
>>> unicode('\x80abc', errors='replace')
u'\ufffdabc'
>>> unicode('\x80abc', errors='ignore')
u'abc'
2, nhưng việc thực hiện mã hóa là một nhiệm vụ chuyên dụng cũng giành được ở đâ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

>>> unicode('\x80abc', errors='strict')     
Traceback (most recent call last):
    ...
UnicodeDecodeError: 'ascii' codec can't decode byte 0x80 in position 0:
ordinal not in range(128)
>>> unicode('\x80abc', errors='replace')
u'\ufffdabc'
>>> unicode('\x80abc', errors='ignore')
u'abc'
2 là hàm
>>> unicode('\x80abc', errors='strict')     
Traceback (most recent call last):
    ...
UnicodeDecodeError: 'ascii' codec can't decode byte 0x80 in position 0:
ordinal not in range(128)
>>> unicode('\x80abc', errors='replace')
u'\ufffdabc'
>>> unicode('\x80abc', errors='ignore')
u'abc'
6 sẽ được thảo luận trong phần về đầu vào và đầu ra.

Unicode theo nghĩa đen trong mã nguồn Python

Trong mã nguồn Python, các chữ Unicode được viết dưới dạng các chuỗi được đặt trước với ký tự ‘U, hoặc‘ U,

>>> unicode('\x80abc', errors='strict')     
Traceback (most recent call last):
    ...
UnicodeDecodeError: 'ascii' codec can't decode byte 0x80 in position 0:
ordinal not in range(128)
>>> unicode('\x80abc', errors='replace')
u'\ufffdabc'
>>> unicode('\x80abc', errors='ignore')
u'abc'
7. Các điểm mã cụ thể có thể được viết bằng chuỗi thoát
>>> unicode('\x80abc', errors='strict')     
Traceback (most recent call last):
    ...
UnicodeDecodeError: 'ascii' codec can't decode byte 0x80 in position 0:
ordinal not in range(128)
>>> unicode('\x80abc', errors='replace')
u'\ufffdabc'
>>> unicode('\x80abc', errors='ignore')
u'abc'
8, theo sau là bốn chữ số hex cho điểm mã. Trình tự thoát
>>> unicode('\x80abc', errors='strict')     
Traceback (most recent call last):
    ...
UnicodeDecodeError: 'ascii' codec can't decode byte 0x80 in position 0:
ordinal not in range(128)
>>> unicode('\x80abc', errors='replace')
u'\ufffdabc'
>>> unicode('\x80abc', errors='ignore')
u'abc'
9 là tương tự nhau, nhưng mong đợi 8 chữ số hex chứ không phải 4.

Các chữ Unicode cũng có thể sử dụng các chuỗi thoát giống như các chuỗi 8 bit, bao gồm

>>> unichr(40960)
u'\ua000'
>>> ord(u'\ua000')
40960
0, nhưng
>>> unichr(40960)
u'\ua000'
>>> ord(u'\ua000')
40960
0 chỉ có hai chữ số hex để nó có thể thể hiện một điểm mã tùy ý. Escapes octal có thể đi lên U+01ff, đó là 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 trình tự thoát cho các điểm mã lớn hơn 127 là tốt với liều nhỏ, nhưng trở thành một khó khăn nếu bạn sử dụng nhiều ký tự có dấu, như bạn sẽ làm trong một chương trình có tin nhắn bằng tiếng Pháp hoặc một số ngôn ngữ sử dụng giọng nói khác. Bạn cũng có thể lắp ráp các chuỗi bằng cách sử dụng chức năng tích hợp

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

>>> unicode('abcdef' + chr(255))    
Traceback (most recent call last):
...
UnicodeDecodeError: 'ascii' codec can't decode byte 0xff in position 6:
ordinal not in range(128)
5, 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 các chữ bằng ngôn ngữ của bạn. Sau đó, bạn có thể chỉnh sửa mã nguồn Python với trình soạn thảo yêu thích của bạn 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 chữ unicode trong bất kỳ mã hóa nào, nhưng bạn phải tuyên bố 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 là dòng đầu tiên hoặc 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 Emacs, để chỉ định các biến cục bộ vào tệp. Emacs hỗ trợ nhiều biến khác nhau, nhưng Python chỉ hỗ trợ ‘mã hóa. Các biểu tượng

>>> unichr(40960)
u'\ua000'
>>> ord(u'\ua000')
40960
3 chỉ ra cho Emac rằng nhận xét là đặc biệt; Họ không có ý nghĩa đối với Python nhưng là một quy ước. Python tìm kiếm
>>> unichr(40960)
u'\ua000'
>>> ord(u'\ua000')
40960
4 hoặc
>>> unichr(40960)
u'\ua000'
>>> ord(u'\ua000')
40960
5 trong bình luận.

Nếu bạn không bao gồm một 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 của Python trước 2,4 là trung tâm Euro và giả sử Latin-1 là mã hóa mặc định cho các tác phẩm theo chuỗi; Trong Python 2.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 đây không có khai báo mã hóa:

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ẽ đưa 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

Python 2.5 trở lên là chặt chẽ hơn và sẽ tạo ra lỗi cú pháp:

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

Thuộc tính unicode

Thông số kỹ thuậ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 ký tự, danh mục của nó, giá trị số nếu có (Unicode có ký tự đại diện cho các chữ số và phân số La Mã 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 Code Point 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 đây 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
5

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
6

Các mã danh mục là chữ viết tắt mô tả bản chất của nhân vật. Chúng được nhóm thành các danh mục như chữ cái, chữ số, số lượng, số lần, dấu chấm câu, hoặc biểu tượng của người Hồi giáo, từ đó được chia thành các tiểu thể loại. Để lấy các mã từ đầu ra ở trên,

>>> unichr(40960)
u'\ua000'
>>> ord(u'\ua000')
40960
6 có nghĩa là ‘chữ cái, chữ thường,
>>> unichr(40960)
u'\ua000'
>>> ord(u'\ua000')
40960
7 có nghĩa là số, số khác,
>>> unichr(40960)
u'\ua000'
>>> ord(u'\ua000')
40960
8 là Mark Mark, không định vị, và
>>> unichr(40960)
u'\ua000'
>>> ord(u'\ua000')
40960
9 là biểu tượng, khác. Xem để biết danh sách các mã danh mục.

Đọc và viết 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 thế nào để bạn có được chuỗi Unicode vào chương trình của bạn và làm thế nào để bạn chuyển đổi Unicode thành một hình thức phù hợp để lưu trữ hoặc truyền?

Nó có thể là bạn có thể 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à điểm đến đầu ra của bạn; Bạn nên kiểm tra xem các thư viện được sử dụng trong ứng dụng của bạn hỗ trợ Unicode tự nhiên. Trình phân tích cú pháp XML thường trả về dữ liệu Unicode chẳng hạn. 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 nó được ghi vào đĩa hoặc gửi qua ổ cắm. Nó có thể tự mình thực hiện tất cả các công việc: mở một tệp, đọc một chuỗi 8 bit từ nó và chuyển đổi chuỗi bằ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?'
0. Tuy nhiên, phương pháp thủ công không được khuyến khích.

Một vấn đề là bản chất đa byte của mã hóa; Một ký tự Unicode có thể được biểu diễn bằng một số byte. Nếu bạn muốn đọc tệp bằng các khối có kích thước tùy ý (giả sử, 1k hoặc 4K), bạn cần viết mã xử lý lỗi để bắt trường hợp chỉ một phần của byte mã hóa một ký tự unicode duy nhất được đọc ở cuối Chunk. Một giải pháp sẽ 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 bạn làm việc với các tệp cực kỳ lớn; Nếu bạn cần đọc tệp 2GB, bạn cần 2GB RAM. (Thêm, thực sự, vì trong ít nhất một khoảnh khắc bạn cần phải 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 để bắt gặp trường hợp của các chuỗi 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

>>> unicode('\x80abc', errors='strict')     
Traceback (most recent call last):
    ...
UnicodeDecodeError: 'ascii' codec can't decode byte 0x80 in position 0:
ordinal not in range(128)
>>> unicode('\x80abc', errors='replace')
u'\ufffdabc'
>>> unicode('\x80abc', errors='ignore')
u'abc'
2 bao gồm một phiên bản của hàm
>>> 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?'
2 trả về một đối tượng giống như tệp giả định nội dung của tệp nằm trong một mã hóa được chỉ định và chấp nhận các tham số Unicode cho các phương thức như
>>> 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?'
3 và
>>> 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?'
4 .

Các tham số chức năng là

>>> 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?'
5.
>>> 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?'
6 có thể là
>>> 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?'
7,
>>> 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?'
8 hoặc
>>> 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?'
9, giống như tham số tương ứng với hàm
>>> 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?'
2 tích hợp thông thường; Thêm
>>> s.find('Was\x9f')                   
Traceback (most recent call last):
    ...
UnicodeDecodeError: 'ascii' codec can't decode byte 0x9f in position 3:
ordinal not in range(128)
>>> s.find(u'Was\x9f')
-1
1 để cập nhật tệp.
>>> s.find('Was\x9f')                   
Traceback (most recent call last):
    ...
UnicodeDecodeError: 'ascii' codec can't decode byte 0x9f in position 3:
ordinal not in range(128)
>>> s.find(u'Was\x9f')
-1
2 song song tương tự với tham số hàm tiêu chuẩn.
>>> unicode('abcdef')
u'abcdef'
>>> s = unicode('abcdef')
>>> type(s)

>>> unicode('abcdef' + chr(255))    
Traceback (most recent call last):
...
UnicodeDecodeError: 'ascii' codec can't decode byte 0xff in position 6:
ordinal not in range(128)
2 là một chuỗi cung cấp mã hóa để sử dụng; Nếu nó rời khỏi
>>> s.find('Was\x9f')                   
Traceback (most recent call last):
    ...
UnicodeDecodeError: 'ascii' codec can't decode byte 0x9f in position 3:
ordinal not in range(128)
>>> s.find(u'Was\x9f')
-1
4, một đối tượng tệp Python thông thường chấp nhận các chuỗi 8 bit được trả về. Mặt khác, một đối tượng trình bao bọc được trả về và dữ liệu được ghi vào hoặc đọc từ đối tượng trình bao sẽ được chuyển đổi khi cần thiết.
>>> unicode('abcdef')
u'abcdef'
>>> s = unicode('abcdef')
>>> type(s)

>>> unicode('abcdef' + chr(255))    
Traceback (most recent call last):
...
UnicodeDecodeError: 'ascii' codec can't decode byte 0xff in position 6:
ordinal not in range(128)
3 Chỉ định hành động cho các lỗi mã hóa và có thể là một trong những giá trị thông thường của ‘nghiêm ngặt,‘ bỏ qua, và ‘thay thế.

Do đó, đọ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
7

Nó cũng có thể mở các tệp ở chế độ cập nhật, cho phép cả đọc và viết:

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

Ký tự Unicode U+FEFF được sử dụng làm nhãn hiệu thứ tự byte (BOM) và thường được viết là ký tự đầu tiên của một tệp để hỗ trợ tự động hóa tệp byte. Một số mã hóa, chẳng hạn như UTF-16, mong đợi một BOM sẽ có mặt khi bắt đầu một tập tin; Khi một mã hóa như vậy được sử dụng, BOM sẽ tự động được viết dưới dạng ký tự đầu tiên và sẽ được giảm âm thầm khi đọc 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 cho các mã hóa Little-Endian và Big-Endian, chỉ định một thứ tự byte cụ thể và don don 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 ngày nay hỗ trợ các tên tệp có 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 Windows, Python sử dụng tên là MB MBCS để chỉ bất kỳ thứ gì mã hóa hiện đang được cấu hình. Trên các hệ thống UNIX, sẽ chỉ có mã hóa hệ thống tập tin nếu bạn đã đặt các biến môi trường

>>> s.find('Was\x9f')                   
Traceback (most recent call last):
    ...
UnicodeDecodeError: 'ascii' codec can't decode byte 0x9f in position 3:
ordinal not in range(128)
>>> s.find(u'Was\x9f')
-1
6 hoặc
>>> s.find('Was\x9f')                   
Traceback (most recent call last):
    ...
UnicodeDecodeError: 'ascii' codec can't decode byte 0x9f in position 3:
ordinal not in range(128)
>>> s.find(u'Was\x9f')
-1
7; Nếu bạn thiên đường, mã hóa mặc định là ASCII.

Hàm

>>> s.find('Was\x9f')                   
Traceback (most recent call last):
    ...
UnicodeDecodeError: 'ascii' codec can't decode byte 0x9f in position 3:
ordinal not in range(128)
>>> s.find(u'Was\x9f')
-1
8 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 thủ công, nhưng ở đó không có nhiều lý do để bận tâm. Khi mở tệp để đọc hoặc viết, bạn thường chỉ có thể cung cấp chuỗi Unicode dưới dạng tên tệp và nó sẽ được tự động chuyển đổi sang mã hóa 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
9

Các chức năng trong mô -đun

>>> s.find('Was\x9f')                   
Traceback (most recent call last):
    ...
UnicodeDecodeError: 'ascii' codec can't decode byte 0x9f in position 3:
ordinal not in range(128)
>>> s.find(u'Was\x9f')
-1
9 như
>>> u = unichr(40960) + u'abcd' + unichr(1972)
>>> u.encode('utf-8')
'\xea\x80\x80abcd\xde\xb4'
>>> u.encode('ascii')                       
Traceback (most recent call last):
    ...
UnicodeEncodeError: 'ascii' codec can't encode character u'\ua000' in
position 0: ordinal not in range(128)
>>> u.encode('ascii', 'ignore')
'abcd'
>>> u.encode('ascii', 'replace')
'?abcd?'
>>> u.encode('ascii', 'xmlcharrefreplace')
'ꀀabcd޴'
0 cũng sẽ chấp nhận tên tệp Unicode.

>>> u = unichr(40960) + u'abcd' + unichr(1972)
>>> u.encode('utf-8')
'\xea\x80\x80abcd\xde\xb4'
>>> u.encode('ascii')                       
Traceback (most recent call last):
    ...
UnicodeEncodeError: 'ascii' codec can't encode character u'\ua000' in
position 0: ordinal not in range(128)
>>> u.encode('ascii', 'ignore')
'abcd'
>>> u.encode('ascii', 'replace')
'?abcd?'
>>> u.encode('ascii', 'xmlcharrefreplace')
'ꀀabcd޴'
1, trả về tên tệp, đặt ra một vấn đề: nó có 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 có chứa các phiên bản được mã hóa?
>>> u = unichr(40960) + u'abcd' + unichr(1972)
>>> u.encode('utf-8')
'\xea\x80\x80abcd\xde\xb4'
>>> u.encode('ascii')                       
Traceback (most recent call last):
    ...
UnicodeEncodeError: 'ascii' codec can't encode character u'\ua000' in
position 0: ordinal not in range(128)
>>> u.encode('ascii', 'ignore')
'abcd'
>>> u.encode('ascii', 'replace')
'?abcd?'
>>> u.encode('ascii', 'xmlcharrefreplace')
'ꀀabcd޴'
1 sẽ thực hiện cả hai, tùy thuộc vào việc bạn cung cấp đường dẫn thư mục dưới dạng chuỗi 8 bit hay chuỗi Unicode. Nếu bạn vượt qua 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 hệ thống tập tin và danh sách các chuỗi unicode sẽ được trả về, trong khi đi qua đườ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 tin mặc định là UTF-8, chạy chương trình 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

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
1

Danh sách đầu tiên chứa các 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 các chương trình nhận biết Unicode

Phần này cung cấp một số gợi ý về việc viết phần mềm liên quan đến 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 thành một mã hóa cụ thể trên đầu ra.

Nếu bạn cố gắng viết các chức năng xử lý chấp nhận cả chuỗi Unicode và 8 bit, bạn sẽ thấy chương trình của mình dễ bị lỗi ở bất cứ nơi 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 nằm trong dữ liệu đầu vào, bạn sẽ nhận được một

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

>>> unicode('abcdef' + chr(255))    
Traceback (most recent call last):
...
UnicodeDecodeError: 'ascii' codec can't decode byte 0xff in position 6:
ordinal not in range(128)
4 vì ký tự đó có thể được xử lý bởi mã hóa ASCII.

Thật dễ dàng để bỏ lỡ 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ỳ điểm nhấn nào; Mọi thứ dường như sẽ hoạt động, nhưng thực sự có một lỗi trong chương trình của bạn đang chờ người dùng đầu tiên cố gắng sử dụng ký tự> 127. Mẹo thứ hai, do đó, là:

Bao gồm các ký tự> 127 và thậm chí tốt hơn, 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, một kỹ thuật phổ biến là kiểm tra các ký tự bất hợp pháp trong một chuỗi trước khi sử dụng chuỗi trong một dòng lệnh được tạo hoặc lưu trữ nó trong cơ sở dữ liệu. Nếu bạn làm điều này, hãy cẩn thận để kiểm tra chuỗi một khi nó ở dạng sẽ được sử dụng hoặc lưu trữ; Nó có thể sử dụng mã hóa để ngụy trang các ký tự. Điều này đặc biệt đúng nếu dữ liệu đầu vào cũng chỉ định mã hóa; Nhiều mã hóa để lại các ký tự được kiểm tra thường được kiểm tra, nhưng Python bao gồm một số mã hóa như

>>> u = unichr(40960) + u'abcd' + unichr(1972)
>>> u.encode('utf-8')
'\xea\x80\x80abcd\xde\xb4'
>>> u.encode('ascii')                       
Traceback (most recent call last):
    ...
UnicodeEncodeError: 'ascii' codec can't encode character u'\ua000' in
position 0: ordinal not in range(128)
>>> u.encode('ascii', 'ignore')
'abcd'
>>> u.encode('ascii', 'replace')
'?abcd?'
>>> u.encode('ascii', 'xmlcharrefreplace')
'ꀀabcd޴'
4 sửa đổi từng ký tự.

Ví dụ, hãy để nói rằng 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 với 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
2

Tuy nhiên, nếu kẻ tấn công có thể chỉ định mã hóa

>>> u = unichr(40960) + u'abcd' + unichr(1972)
>>> u.encode('utf-8')
'\xea\x80\x80abcd\xde\xb4'
>>> u.encode('ascii')                       
Traceback (most recent call last):
    ...
UnicodeEncodeError: 'ascii' codec can't encode character u'\ua000' in
position 0: ordinal not in range(128)
>>> u.encode('ascii', 'ignore')
'abcd'
>>> u.encode('ascii', 'replace')
'?abcd?'
>>> u.encode('ascii', 'xmlcharrefreplace')
'ꀀabcd޴'
4, chúng có thể vượt qua
>>> u = unichr(40960) + u'abcd' + unichr(1972)
>>> u.encode('utf-8')
'\xea\x80\x80abcd\xde\xb4'
>>> u.encode('ascii')                       
Traceback (most recent call last):
    ...
UnicodeEncodeError: 'ascii' codec can't encode character u'\ua000' in
position 0: ordinal not in range(128)
>>> u.encode('ascii', 'ignore')
'abcd'
>>> u.encode('ascii', 'replace')
'?abcd?'
>>> u.encode('ascii', 'xmlcharrefreplace')
'ꀀabcd޴'
6, đó là dạng mã hóa cơ sở-64 của chuỗi
>>> u = unichr(40960) + u'abcd' + unichr(1972)
>>> u.encode('utf-8')
'\xea\x80\x80abcd\xde\xb4'
>>> u.encode('ascii')                       
Traceback (most recent call last):
    ...
UnicodeEncodeError: 'ascii' codec can't encode character u'\ua000' in
position 0: ordinal not in range(128)
>>> u.encode('ascii', 'ignore')
'abcd'
>>> u.encode('ascii', 'replace')
'?abcd?'
>>> u.encode('ascii', 'xmlcharrefreplace')
'ꀀabcd޴'
7, để đọc một tệp hệ thống. Mã trên tìm kiếm các ký tự
>>> u = unichr(40960) + u'abcd' + unichr(1972)
>>> u.encode('utf-8')
'\xea\x80\x80abcd\xde\xb4'
>>> u.encode('ascii')                       
Traceback (most recent call last):
    ...
UnicodeEncodeError: 'ascii' codec can't encode character u'\ua000' in
position 0: ordinal not in range(128)
>>> u.encode('ascii', 'ignore')
'abcd'
>>> u.encode('ascii', 'replace')
'?abcd?'
>>> u.encode('ascii', 'xmlcharrefreplace')
'ꀀabcd޴'
8 ở dạng được mã hóa và bỏ lỡ ký tự nguy hiểm ở dạng giải mã kết quả.

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

Cảm ơn những người sau đây đã lưu ý các lỗi hoặc đưa ra đề xuất về bài viết này: Nicholas Bastin, Marius Gedminas, Kent Johnson, Ken Krugler, Marc-André Lemburg, Martin von Löwis, Chad Whitacre.

Phiên bản 1.0: Đăng ngày 5 tháng 8 năm 2005.

Phiên bản 1.01: Đăng ngày 7 tháng 8 năm 2005. Sửa lỗi thực tế và đánh dấu; Thêm một số liên kết.

Phiên bản 1.02: Đăng ngày 16 tháng 8 năm 2005. Sửa lỗi thực tế.

Phiên bản 1.03: Được đăng ngày 20 tháng 6 năm 2010. Ghi chú rằng Python 3.x không được bảo hiểm và Howto chỉ bao gồm 2.x.