Python cho người Việt

Python cho người Việt

Entries tagged “encode”

In chuỗi unicode ra màn hình

written by Nguyễn Thành Nam, on Dec 16, 2009 9:33:45 PM.

Một ngày nào đấy, có lẽ bạn sẽ rất bực mình khi gặp phải một lỗi tương tự như sau:

c:\tmp>c:\Python26\python.exe helloworld.py
Traceback (most recent call last):
  File "helloworld.py", line 3, in <module>
    print u"Xin chào bạn, Python!"
  File "c:\Python26\lib\encodings\cp437.py", line 12, in encode
    return codecs.charmap_encode(input,errors,encoding_map)
UnicodeEncodeError: 'charmap' codec can't encode character u'\u1ea1' in position
 10: character maps to <undefined>

c:\tmp>

Mã nguồn của helloworld.py chỉ đơn giản như sau:

# -*- encoding: utf-8 -*-

print u"Xin chào bạn, Python!"

Lỗi này xảy ra vì chúng ta đang in một chuỗi unicode, với các ký tự nằm ngoài bảng mã ASCII (hoặc bảng mã mặc định của màn hình hiện tại).

Khi gặp phải các ký tự nằm ngoài bảng mã này, Python mặc định sẽ nâng một biệt lệ cho biết chính xác đó là ký tự nào, nằm ở vị trí nào. Như ví dụ trên, đó là ký tự có mã unicode là 1EA1 nằm tại vị trí thứ 10 (vị trí bắt đầu là 0) trong chuỗi Xin chào bạn, Python!.

Có một số cách để khắc phục lỗi này, từ việc thay đổi một số biến môi trường, cho đến việc sửa từng dòng lệnh. Tất cả đều nhằm một mục đích là chuyển chuỗi unicode cần in thành chuỗi byte theo bảng mã UTF-8.

  • Thay đổi biến môi trường: Biến môi trường PYTHONIOENCODING được dùng để định nghĩa bảng mã cho các bộ nhập chuẩn, bộ xuất chuẩn, và bộ lỗi chuẩn (stdin, stdout, stderr). Chúng ta có thể định nghĩa biến môi trường này thành utf-8 như sau:
c:\tmp>set PYTHONIOENCODING=utf-8

c:\tmp>c:\Python26\python.exe helloworld.py
Xin chào bạn, Python!

c:\tmp>
  • Thay đổi bộ xuất chuẩn: Bộ xuất chuẩn (sys.stdout) có thể được “gói” trong bảng mã mới thông qua mô-đun codecs.
# -*- encoding: utf-8 -*-
import codecs
import sys

writer_factory = codecs.getwriter("utf-8")
sys.stdout = writer_factory(sys.stdout)

print u"Xin chào bạn, Python!"
c:\tmp>c:\Python26\python helloworld.py
Xin chào bạn, Python!

c:\tmp>
  • Thay đổi từng dòng lệnh print:
# -*- encoding: utf-8 -*-
print u"Xin chào bạn, Python!".encode("utf-8")
c:\tmp>c:\Python26\python helloworld.py
Xin chào bạn, Python!

c:\tmp>

Như chúng ta thấy, cách nào cũng dẫn đến cùng một kết quả mong muốn. Việc áp dụng cách nào sẽ phụ thuộc vào hoàn cảnh của từng chương trình.