Để trả lời "tại sao", chúng ta cần phải hiểu được loại 1.được xây dựng sẵn của Python 2.x, file.encoding
và mối quan hệ của chúng.
Giao diện đối tượng được xây dựng trong file
với byte nguyên --- luôn đọc và ghi byte thô.
Thuộc tính encoding
mô tả mã hóa byte nguyên trong luồng. Thuộc tính này có thể có hoặc không có mặt và thậm chí có thể không đáng tin cậy (ví dụ: chúng tôi đặt PYTHONIOENCODING
không chính xác trong trường hợp luồng chuẩn).
Thời gian duy nhất bất kỳ chuyển đổi tự động nào được thực hiện bởi file
đối tượng là khi viết đối tượng unicode
cho luồng đó. Trong trường hợp đó, nó sẽ sử dụng file.encoding
nếu có sẵn để thực hiện chuyển đổi.
Trong trường hợp đọc dữ liệu, đối tượng tệp sẽ không thực hiện bất kỳ chuyển đổi nào vì nó trả về byte thô. Thuộc tính encoding
trong trường hợp này là gợi ý để người dùng thực hiện chuyển đổi theo cách thủ công.
file.encoding
được đặt trong trường hợp của bạn vì bạn đặt biến số PYTHONIOENCODING
và thuộc tính'encoding
được đặt tương ứng. Để có được một dòng văn bản, chúng ta phải quấn nó theo cách thủ công như bạn đã làm trong mã ví dụ của bạn.
Để suy nghĩ về cách khác, hãy tưởng tượng rằng chúng tôi không có loại văn bản riêng biệt (như là unicode
hoặc Python 3's str
). Chúng tôi vẫn có thể làm việc với văn bản bằng cách sử dụng byte thô, nhưng vẫn theo dõi mã hóa được sử dụng. Đây là loại cách file.encoding
có nghĩa là để được sử dụng (được sử dụng để theo dõi mã hóa). Trình bao bọc trình đọc mà chúng tôi tạo tự động thực hiện theo dõi và chuyển đổi cho chúng tôi.
Tất nhiên, tự động gói sys.stdin
sẽ đẹp hơn (và đó là Python 3.x), nhưng thay đổi hành vi mặc định là sys.stdin
bằng Python 2.x sẽ phá vỡ tính tương thích ngược.
Sau đây là một so sánh của sys.stdin
bằng Python 2.x và 3.x:
# Python 2.7.4
>>> import sys
>>> type(sys.stdin)
<type 'file'>
>>> sys.stdin.encoding
'UTF-8'
>>> w = sys.stdin.readline()
## ... type stuff - enter
>>> type(w)
<type 'str'> # In Python 2.x str is just raw bytes
>>> import locale
>>> locale.getdefaultlocale()
('en_US', 'UTF-8')
Các io.TextIOWrapper
class là một phần của thư viện chuẩn từ Python 2.6. Lớp này có thuộc tính encoding
được sử dụng để chuyển đổi byte thô thành Unicode từ và đến.
# Python 3.3.1
>>> import sys
>>> type(sys.stdin)
<class '_io.TextIOWrapper'>
>>> sys.stdin.encoding
'UTF-8'
>>> w = sys.stdin.readline()
## ... type stuff - enter
>>> type(w)
<class 'str'> # In Python 3.x str is Unicode
>>> import locale
>>> locale.getdefaultlocale()
('en_US', 'UTF-8')
Thuộc tính buffer
cung cấp quyền truy cập vào luồng luồng byte nguyên stdin
; đây thường là BufferedReader
. Lưu ý dưới đây rằng nó không có thuộc tính encoding
.
# Python 3.3.1 again
>>> type(sys.stdin.buffer)
<class '_io.BufferedReader'>
>>> w = sys.stdin.buffer.readline()
## ... type stuff - enter
>>> type(w)
<class 'bytes'> # bytes is (kind of) equivalent to Python 2 str
>>> sys.stdin.buffer.encoding
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: '_io.BufferedReader' object has no attribute 'encoding'
Trong Python 3 sự có mặt hoặc vắng mặt của thuộc tính được sử dụng.
Phiên bản python nào? thử 'line.decode (your_encoding) .upper()' – JBernardo
Câu trả lời ngắn gọn: Vì bạn đang sử dụng phiên bản Python lỗi thời đầy hành lý lịch sử. – phihag
@JBernardo Python phiên bản là 2.7.3 (theo FreeBSD 9) 'line.decode (sys.stdin.encoding) .upper()' làm việc của khóa học. Nhưng câu hỏi của tôi là tại sao chúng ta cần tất cả điều này? –