Tôi nghĩ rằng tôi biết mọi thứ về mã hóa và Python, nhưng hôm nay tôi gặp một vấn đề lạ: mặc dù giao diện điều khiển được đặt thành mã trang 850 - và Python báo cáo chính xác - tham số tôi đặt trên dòng lệnh dường như được mã hóa trong trang mã 1252. Nếu tôi cố gắng giải mã chúng bằng sys.stdin.encoding, tôi nhận được kết quả sai. Nếu tôi giả sử 'cp1252', bỏ qua những gì sys.stdout.encoding báo cáo, nó hoạt động.Python, cửa sổ giao diện điều khiển và mã hóa (cp 850 vs cp1252)
Tôi có thiếu thứ gì đó hay đây là lỗi trong Python? Các cửa sổ ? Lưu ý: Tôi đang chạy Python 2.6.6 trên Windows 7 EN, ngôn ngữ được đặt thành tiếng Pháp (Thụy Sĩ).
Trong chương trình thử nghiệm dưới đây, tôi kiểm tra xem các chữ được giải thích chính xác và có thể được in hay không - tác phẩm này hoạt động. Nhưng tất cả các giá trị tôi vượt qua trên dòng lệnh dường như được mã hóa sai:
#!/usr/bin/python
# -*- encoding: utf-8 -*-
import sys
literal_mb = 'utf-8 literal: üèéÃÂç€ÈÚ'
literal_u = u'unicode literal: üèéÃÂç€ÈÚ'
print "Testing literals"
print literal_mb.decode('utf-8').encode(sys.stdout.encoding,'replace')
print literal_u.encode(sys.stdout.encoding,'replace')
print "Testing arguments (stdin/out encodings:",sys.stdin.encoding,"/",sys.stdout.encoding,")"
for i in range(1,len(sys.argv)):
arg = sys.argv[i]
print "arg",i,":",arg
for ch in arg:
print " ",ch,"->",ord(ch),
if ord(ch)>=128 and sys.stdin.encoding == 'cp850':
print "<-",ch.decode('cp1252').encode(sys.stdout.encoding,'replace'),"[assuming input was actually cp1252 ]"
else:
print ""
Trong một giao diện điều khiển mới được tạo ra, khi chạy
C:\dev>test-encoding.py abcé€
tôi nhận được kết quả như sau
Testing literals
utf-8 literal: üèéÃÂç?ÈÚ
unicode literal: üèéÃÂç?ÈÚ
Testing arguments (stdin/out encodings: cp850/cp850)
arg 1 : abcÚÇ
a -> 97
b -> 98
c -> 99
Ú -> 233 <- é [assuming input was actually cp1252 ]
Ç -> 128 <- ? [assuming input was actually cp1252 ]
khi Tôi mong đợi ký tự thứ 4 có giá trị thứ tự là thay vì 233 (xem các trang mã 850 và 1252).
Lưu ý: giá trị 128 cho biểu tượng đồng euro là một điều bí ẩn - vì cp850 không có. Nếu không '?' được mong đợi - cp850 không thể in các ký tự và tôi đã sử dụng 'thay thế' trong các chuyển đổi.
Nếu tôi thay đổi trang mã của giao diện điều khiển để 1252 bằng cách phát hành chcp 1252
và chạy lệnh tương tự, tôi (chính xác) được
Testing literals
utf-8 literal: üèéÃÂç€ÈÚ
unicode literal: üèéÃÂç€ÈÚ
Testing arguments (stdin/out encodings: cp1252/cp1252)
arg 1 : abcé€
a -> 97
b -> 98
c -> 99
é -> 233
€ -> 128
Bất kỳ ý tưởng những gì tôi đang thiếu?
Chỉnh sửa 1: Tôi vừa mới kiểm tra bằng cách đọc sys.stdin. Điều này làm việc như mong đợi: trong cp850, gõ 'é' kết quả trong một giá trị thứ tự của 130. Vì vậy, vấn đề là thực sự cho dòng lệnh chỉ. Vì vậy, là dòng lệnh xử lý khác với đầu vào tiêu chuẩn?
Chỉnh sửa 2: Có vẻ như tôi đã có từ khóa sai. Tôi đã tìm thấy một chủ đề rất gần khác về SO: Read Unicode characters from command-line arguments in Python 2.x on Windows. Tuy nhiên, nếu dòng lệnh không được mã hóa như sys.stdin, và vì sys.getdefaultencoding() báo cáo 'ascii', có vẻ như không có cách nào để biết mã hóa thực tế của nó. Tôi tìm thấy câu trả lời bằng cách sử dụng phần mở rộng win32 khá hacky.
Đối với Linux thường 'locale.getpreferredencoding()' hoặc, sau khi sử dụng 'locale.setlocale()' - 'locale.getlocale() [1]' cung cấp mã hóa đúng cho giao diện điều khiển và môi trường. Mặc dù, mã hóa UTF-8 thường đủ tốt cho hầu hết các hệ thống hiện đại (vì vậy nó là giá trị giảm tốt nhất). –