2012-11-19 15 views
11

Tôi đang trên CMD trong Windows 8 và tôi đã đặt mã hóa thành 65001 (chcp 65001). Tôi đang sử dụng Python 2.7.2 (ActivePython 2.7.2.5) và tôi đã đặt biến môi trường PYTHONSTARTUP thành "bootstrap.py".Tại sao tôi nhận được IOErrors khi viết Unicode vào CMD? (Với codepage 65001)

bootstrap.py:

import codecs 
codecs.register(
    lambda name: name == 'cp65001' and codecs.lookup('UTF-8') or None 
) 

này cho phép tôi in ASCII:

>>> print 'hello' 
hello 
>>> print u'hello' 
hello 

Nhưng các lỗi tôi nhận được khi tôi cố gắng in một chuỗi Unicode với các ký tự ASCII làm cho không có cảm giác với tôi. Ở đây tôi cố gắng in một vài chuỗi có chứa các ký hiệu Bắc Âu (tôi đã thêm ngắt dòng phụ giữa các bản in để dễ đọc):

>>> print u'æøå' 
��øåTraceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
IOError: [Errno 2] No such file or directory 

>>> print u'åndalsnes' 
��ndalsnes 

>>> print u'åndalsnesæ' 
��ndalsnesæTraceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
IOError: [Errno 22] Invalid argument 

>>> print u'Øst' 
��st 

>>> print u'uØst' 
uØstTraceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
IOError: [Errno 22] Invalid argument 

>>> print u'ØstÆØÅæøå' 
��stÆØÅæøåTraceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
IOError: [Errno 22] Invalid argument 

>>> print u'_ØstÆØÅæøå' 
_ØstÆØÅæøåTraceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
IOError: [Errno 22] Invalid argument 

Như bạn thấy nó không phải lúc nào cũng gây ra lỗi (và thậm chí không tăng cùng một lỗi mỗi lần) và các ký hiệu Bắc Âu chỉ được hiển thị chính xác thỉnh thoảng.

Ai đó có thể giải thích hành vi này, hoặc ít nhất giúp tôi tìm hiểu cách in Unicode sang CMD chính xác?

+2

Đây là một tình huống ác mộng. Và nó đã được thảo luận một lần gazillion ở đây trên SO và ở nơi khác. Ví dụ: http://www.google.com/search?q=print+unicode+windows+console+python –

+0

Giải pháp đơn giản nhất là sử dụng Python 3.3, nếu bạn có thể. Nó có một [cp65001 codec] (http://docs.python.org/3/whatsnew/3.3.html#codecs). – eryksun

+0

@PiotrDobrogost: Hãy giới thiệu cho tôi một trường hợp khác như thế này nếu bạn có thể tìm thấy nó (và tôi ** không ** có nghĩa là lỗi giải mã Unicode!) – Hubro

Trả lời

1

Hãy thử này:

# -*- coding: utf-8 -*- 
    from __future__ import unicode_literals 
    print u'æøå' 

Tận dụng từ __future__ unicode_literals nhập khẩu sẽ có ích trong một phiên python tương tác.

Chắc chắn bạn có thể viết Unicode cho bảng điều khiển thành công khi sử dụng WriteConsoleW. Điều này làm việc bất kể trang mã giao diện điều khiển, bao gồm 65001. Mã here làm như vậy (nó cho Python 2.x, nhưng bạn sẽ được gọi WriteConsoleW từ C anyway).

WriteConsoleW có một lỗi mà tôi biết, có nghĩa là nó fails when writing more than 26608 characters at once. Thật dễ dàng để làm việc xung quanh bằng cách giới hạn lượng dữ liệu được truyền trong một cuộc gọi duy nhất.

Phông chữ không phải là vấn đề của Python, nhưng mã hóa là. Nó không có ý nghĩa để không sản xuất các ký tự đúng chỉ vì một số người dùng có thể không có phông chữ được lựa chọn có thể hiển thị các ký tự đó. Lỗi này sẽ được mở lại.

(Để hoàn thành, có thể hiển thị Unicode trên bảng điều khiển bằng các phông chữ không phải là Bảng điều khiển Lucida và Consolas, nhưng requires a registry hack.) Tôi hy vọng điều đó sẽ hữu ích.

+0

Tôi tin rằng WriteConsoleW bị giới hạn ở UCS-2, tức là bạn không thể sử dụng các ký tự từ các mặt phẳng bổ sung. Nhưng trong hầu hết các trường hợp, đây không phải là vấn đề. –

Các vấn đề liên quan