Hướng dẫn python unicode list - danh sách unicode python

Release:1.12

Điều này đã thảo luận về hỗ trợ Python cho Unicode 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.

Nội dung chính ShowShow

  • Giới thiệu về Unicode¶
  • Lịch sử mã ký tự
  • Định nghĩa¶
  • Python sườn Unicode Hỗ trợ Không
  • Loại chuỗi
  • Chuyển đổi sang byte¶
  • Unicode theo nghĩa đen trong mã nguồn Python
  • Thuộc tính unicode
  • Đọc và viết dữ liệu Unicode
  • Tên tệp Unicode
  • Mẹo để viết các chương trình nhận biết Unicode
  • Sự nhìn nhận¶

Giới thiệu về Unicode¶

Lịch sử mã ký tự

Định nghĩa¶

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

Loại chuỗi

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

Chuyển đổi sang byte¶

Unicode theo nghĩa đen trong mã nguồn Pythonde facto conventions that were invented by one company or another and managed to catch on.

Thuộc tính unicode

Đọc và viết dữ liệu Unicode

Tên tệp Unicode

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

Sự nhìn nhận¶

Định nghĩa¶

Python sườn Unicode Hỗ trợ Khôngcharacter 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.

Loại chuỗicode 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 (4,810 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.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 (1,114,111 thập phân). 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à giá trị từ 0 đến 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.encoding.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 hàm C hiện có như strlen (), do đó, một gia đình mới gồm các hàm chuỗi rộng sẽ cần được sử dụng.strlen(), so a new family of wide string functions would need to be used.strlen(), so a new family of wide string functions would need to be used.
  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. Các quy tắc để chuyển đổi một chuỗi unicode thành mã hóa ASCII, ví dụ, rất đơn giản; Đối với mỗi điểm mã:

  1. Nếu điểm mã là
  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 làm tăng ngoại lệ UnicodeEncodeError trong trường hợp này.)UnicodeEncodeError exception in this case.)UnicodeEncodeError exception in this case.)

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ư strcpy () và được gửi qua các giao thức có thể xử lý số byte bằng 0.strcpy() and sent through protocols that can’t handle zero bytes.strcpy() and sent through protocols that can’t handle zero bytes.
  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 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 chuỗi

Kể từ Python 3.0, ngôn ngữ có loại STR có chứa các ký tự Unicode, nghĩa là bất kỳ chuỗi nào được tạo bằng cách sử dụng "Unicoderocks!", 'Unicoderocks!', Hoặc cú pháp chuỗi được trích xuất ba được lưu trữ dưới dạng Unicode.str type that contain Unicode characters, meaning any string created using "unicoderocks!", 'unicoderocks!', or the triple-quoted string syntax is stored as Unicode.str type that contain Unicode characters, meaning any string created using "unicode rocks!", 'unicode rocks!', or the triple-quoted string syntax is stored as Unicode.

Để chèn một ký tự unicode không phải là một phần ASCII, ví dụ: bất kỳ chữ cái nào có điểm nhấn, người ta có thể sử dụng các chuỗi thoát trong các chữ cái của chúng như vậy:

>>> "\N{GREEK CAPITAL LETTER DELTA}"  # Using the character name
'\u0394'
>>> "\u0394"                          # Using a 16-bit hex value
'\u0394'
>>> "\U00000394"                      # Using a 32-bit hex value
'\u0394'

Ngoài ra, người ta có thể tạo một chuỗi bằng phương thức decode () của byte. Phương thức này có một mã hóa, chẳng hạn như UTF-8, và, tùy chọn, một đối số lỗi.decode() method of bytes. This method takes an encoding, such as UTF-8, and, optionally, an errors argument.decode() method of bytes. This method takes an encoding, such as UTF-8, and, optionally, an errors argument.

Đối số lỗi 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 (nâng cao ngoại lệ UnicodedecodeError),‘ Thay thế (sử dụng 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:UnicodeDecodeError exception), ‘replace’ (use U+FFFD, ‘REPLACEMENT CHARACTER’), or ‘ignore’ (just leave the character out of the Unicode result). The following examples show the differences:UnicodeDecodeError exception), ‘replace’ (use U+FFFD, ‘REPLACEMENT CHARACTER’), or ‘ignore’ (just leave the character out of the Unicode result). The following examples show the differences:

>>> b'\x80abc'.decode("utf-8", "strict")
Traceback (most recent call last):
  File "", line 1, in ?
UnicodeDecodeError: 'utf8' codec can't decode byte 0x80 in position 0:
                    unexpected code byte
>>> b'\x80abc'.decode("utf-8", "replace")
'?abc'
>>> b'\x80abc'.decode("utf-8", "ignore")
'abc'

(Trong ví dụ mã này, ký tự thay thế Unicode đã được thay thế bằng dấu hỏi vì nó có thể không được hiển thị trên một số hệ thống.)

Mã hóa được chỉ định là các chuỗi chứa tên mã hóa. Python 3.2 đ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.

Các chuỗi unicode một ký tự cũng có thể được tạo với hàm tích hợp chr (), 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 ord () tích hợp có chuỗi unicode một ký tự và trả về giá trị điểm mã:chr() built-in function, which takes integers and returns a Unicode string of length 1 that contains the corresponding code point. The reverse operation is the built-in ord() function that takes a one-character Unicode string and returns the code point value:chr() built-in function, which takes integers and returns a Unicode string of length 1 that contains the corresponding code point. The reverse operation is the built-in ord() function that takes a one-character Unicode string and returns the code point value:

>>> chr(57344)
'\ue000'
>>> ord('\ue000')
57344

Chuyển đổi sang byte¶

Một phương thức STR quan trọng khác là .encode ([mã hóa], [Lỗi = 'nghiêm ngặt']), trả về biểu diễn byte của chuỗi unicode, được mã hóa trong mã hóa được yêu cầu. Tham số lỗi giống như tham số của phương thức decode (), với một khả năng bổ sung; Cũng như ’nghiêm ngặt,‘ bỏ qua, và ‘thay thế (trong trường hợp này là chèn một dấu hỏi thay vì ký tự không thể kiểm soát được), 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:.encode([encoding],[errors='strict']), which returns a bytes representation of the Unicode string, encoded in the requested encoding. The errors parameter is the same as the parameter of the decode() method, with one additional possibility; as well as ‘strict’, ‘ignore’, and ‘replace’ (which in this case inserts a question mark instead of the unencodable character), you can also pass ‘xmlcharrefreplace’ which uses XML’s character references. The following example shows the different results:.encode([encoding], [errors='strict']), which returns a bytes representation of the Unicode string, encoded in the requested encoding. The errors parameter is the same as the parameter of the decode() method, with one additional possibility; as well as ‘strict’, ‘ignore’, and ‘replace’ (which in this case inserts a question mark instead of the unencodable character), you can also pass ‘xmlcharrefreplace’ which uses XML’s character references. The following example shows the different results:

>>> u = chr(40960) + 'abcd' + chr(1972)
>>> u.encode('utf-8')
b'\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')
b'abcd'
>>> u.encode('ascii', 'replace')
b'?abcd?'
>>> u.encode('ascii', 'xmlcharrefreplace')
b'ꀀabcd޴'

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 Codecs. 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 so với thoải mái, vì vậy tôi sẽ không mô tả mô-đun Codecs ở đâ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 Codecs, 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 được ở đây. Tham khảo tài liệu Python để tìm hiểu thêm về mô -đun này.codecs module. However, the encoding and decoding functions returned by this module are usually more low-level than is comfortable, so I’m not going to describe the codecs module here. If you need to implement a completely new encoding, you’ll need to learn about the codecs module interfaces, but implementing encodings is a specialized task that also won’t be covered here. Consult the Python documentation to learn more about this module.codecs module. However, the encoding and decoding functions returned by this module are usually more low-level than is comfortable, so I’m not going to describe the codecs module here. If you need to implement a completely new encoding, you’ll need to learn about the codecs module interfaces, but implementing encodings is a specialized task that also won’t be covered here. Consult the Python documentation to learn more about this module.

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

Trong mã nguồn Python, các điểm mã unicode cụ thể có thể được viết bằng chuỗi thoát \ u, theo sau là bốn chữ số hex đưa ra điểm mã. Trình tự thoát \ u tương tự nhau, nhưng mong đợi tám chữ số hex, không phải bốn:\u escape sequence, which is followed by four hex digits giving the code point. The \U escape sequence is similar, but expects eight hex digits, not four:\u escape sequence, which is followed by four hex digits giving the code point. The \U escape sequence is similar, but expects eight hex digits, not four:

>>> s = "a\xac\u1234\u20ac\U00008000"
          ^^^^ two-digit hex escape
               ^^^^^ four-digit Unicode escape
                          ^^^^^^^^^^ eight-digit Unicode escape
>>> for c in s:  print(ord(c), end=" ")
...
97 172 4660 8364 32768

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 hàm tích hợp chr (), nhưng điều này thậm chí còn tẻ nhạt hơn.chr() built-in function, but this is even more tedious.chr() built-in function, but this is even more tedious.

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 mã nguồn trong UTF-8 theo mặc định, nhưng bạn có thể sử dụng hầu hết mọi mã hóa nếu bạn tuyên bố mã hóa đượ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:

#!/usr/bin/env python
# -*- coding: latin-1 -*-

u = 'abcdé'
print(ord(u[-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 -* - chỉ ra các 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 mã hóa: Tên hoặc mã hóa = Tên trong bình luận.-*- symbols indicate to Emacs that the comment is special; they have no significance to Python but are a convention. Python looks for coding:name or coding=name in the comment.-*- symbols indicate to Emacs that the comment is special; they have no significance to Python but are a convention. Python looks for coding: name or coding=name in the comment.

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ẽ được UTF-8 như đã đề cập.

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ể:

import unicodedata

u = chr(233) + chr(0x0bf2) + chr(3972) + chr(6000) + chr(13231)

for i, c in enumerate(u):
    print(i, '%04x' % ord(c), unicodedata.category(c), end=" ")
    print(unicodedata.name(c))

# Get numeric value of second character
print(unicodedata.numeric(u[1]))

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
0

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, 'll' có nghĩa là ‘chữ cái, chữ thường Xem để biết danh sách các mã danh mục.'Ll' means ‘Letter, lowercase’, 'No' means “Number, other”, 'Mn' is “Mark, nonspacing”, and 'So' is “Symbol, other”. See for a list of category codes.'Ll' means ‘Letter, lowercase’, 'No' means “Number, other”, 'Mn' is “Mark, nonspacing”, and 'So' is “Symbol, other”. See for a list of category codes.

Đọ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 chuỗi byte 8 bit từ nó và chuyển đổi chuỗi bằng str (byte, mã hóa). Tuy nhiên, phương pháp thủ công không được khuyến khích.str(bytes,encoding). However, the manual approach is not recommended.str(bytes, encoding). However, the manual approach is not recommended.

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: hàm Open in () tích hợp có thể 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ư .Read () và .viết(). Điều này hoạt động thông qua các tham số mã hóa và lỗi của Open () được giải thích giống như các phương thức trong các đối tượng chuỗi mã hóa () và giải mã ().open() function can return a file-like object that assumes the file’s contents are in a specified encoding and accepts Unicode parameters for methods such as .read() and .write(). This works through open()‘s encoding and errors parameters which are interpreted just like those in string objects’ encode() and decode() methods.open() function can return a file-like object that assumes the file’s contents are in a specified encoding and accepts Unicode parameters for methods such as .read() and .write(). This works through open()‘s encoding and errors parameters which are interpreted just like those in string objects’ encode() and decode() methods.

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
1

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
2

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.

Ở một số khu vực, cũng là quy ước để sử dụng một BOM BOM khi bắt đầu các tệp được mã hóa UTF-8; Tên này là sai lệch vì UTF-8 không phụ thuộc vào thứ tự byte. Dấu chỉ đơn giản là thông báo rằng tệp được mã hóa trong UTF-8. Sử dụng codec ‘UTF-8-SIG để tự động bỏ qua dấu nếu có để đọc các tệp đó.

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 Lang hoặc LC_ctype; Nếu bạn thiên đường, mã hóa mặc định là ASCII.LANG or LC_CTYPE environment variables; if you haven’t, the default encoding is ASCII.LANG or LC_CTYPE environment variables; if you haven’t, the default encoding is ASCII.

Hàm sys.getFilesystemEncoding () 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:sys.getfilesystemencoding() function returns the encoding to use on your current system, in case you want to do the encoding manually, but there’s not much reason to bother. When opening a file for reading or writing, you can usually just provide the Unicode string as the filename, and it will be automatically converted to the right encoding for you:sys.getfilesystemencoding() function returns the encoding to use on your current system, in case you want to do the encoding manually, but there’s not much reason to bother. When opening a file for reading or writing, you can usually just provide the Unicode string as the filename, and it will be automatically converted to the right encoding for you:

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

Các chức năng trong mô -đun HĐH như os.stat () cũng sẽ chấp nhận tên tệp unicode.os module such as os.stat() will also accept Unicode filenames.os module such as os.stat() will also accept Unicode filenames.

Function os.listdir (), trả về tên tệp, nêu 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 byte chứa các phiên bản được mã hóa? Os.ListDir () 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 byte hay chuỗi unicode. Nếu bạn vượt qua chuỗi Unicode dưới dạng đườ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 truyền một đường dẫn byte sẽ trả về các phiên bản chuỗi byte 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:os.listdir(), which returns filenames, raises an issue: should it return the Unicode version of filenames, or should it return byte strings containing the encoded versions? os.listdir() will do both, depending on whether you provided the directory path as a byte string or a Unicode string. If you pass a Unicode string as the path, filenames will be decoded using the filesystem’s encoding and a list of Unicode strings will be returned, while passing a byte path will return the byte string versions of the filenames. For example, assuming the default filesystem encoding is UTF-8, running the following program:os.listdir(), which returns filenames, raises an issue: should it return the Unicode version of filenames, or should it return byte strings containing the encoded versions? os.listdir() will do both, depending on whether you provided the directory path as a byte string or a Unicode string. If you pass a Unicode string as the path, filenames will be decoded using the filesystem’s encoding and a list of Unicode strings will be returned, while passing a byte path will return the byte string versions of the filenames. For example, assuming the default filesystem encoding is UTF-8, running the following program:

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

sẽ tạo ra đầu ra sau:

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

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.

Lưu ý rằng trong hầu hết các trường hợp, API unicode nên được sử dụng. Các API byte chỉ nên được sử dụng trên các hệ thống nơi có thể có tên tệp không thể mã hóa, tức là các hệ thống UNIX.

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à byte, 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. Không có mã hóa hoặc giải mã tự động nếu bạn làm, ví dụ: STR+byte, một kiểu mẫu được nâng lên cho biểu thức này.str+bytes, a TypeError is raised for this expression.str + bytes, a TypeError is raised for this expression.

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ư 'base64' sửa đổi mọi ký tự.'base64' that modify every single character.'base64' that modify every single character.

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:

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

Tuy nhiên, nếu kẻ tấn công có thể chỉ định mã hóa 'base64', chúng có thể vượt qua 'l2v0yy9wyxnzd2q =', là dạng mã hóa cơ sở 64 của chuỗi '/etc/passwd', để đọc một tệp hệ thống. Mã trên tìm kiếm các ký tự '/' ở dạng được mã hóa và bỏ lỡ ký tự nguy hiểm ở dạng được giải mã kết quả.'base64' encoding, they could pass 'L2V0Yy9wYXNzd2Q=', which is the base-64 encoded form of the string '/etc/passwd', to read a system file. The above code looks for '/' characters in the encoded form and misses the dangerous character in the resulting decoded form.'base64' encoding, they could pass 'L2V0Yy9wYXNzd2Q=', which is the base-64 encoded form of the string '/etc/passwd', to read a system file. The above code looks for '/' characters in the encoded form and misses the dangerous character in the resulting decoded form.

Sự nhìn nhậ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.