Gõ tiếng việt trong python

Xử lý tiếng Việt bằng Python :

Để có thể type được tiếng Việt trong môi trường lập trình Python và save thành file .py, bạn cần phải thêm 1 thông báo vào đầu chương trình :

#!/usr/bin/python

# -*- coding: utf8 -*-

Từ bây giờ, tôi mặc định chương trình luôn có đoạn khai báo font chữ này.

Hiện tại, định dạng chữ Unicode đang được sử dụng rất phổ biến và (có lẽ) là phần lớn tiếng Việt dưới dạng số đều được xử lý dưới định dạng này. Về lịch sử và khái niệm Unicode, bạn có thể tham khảo ở đây.

Vậy là bạn đã hiểu tại sao ta lại sử dụng Unicode, và tại sao dòng thông báo trên kia lại là

# -*- coding: utf8 -*-

Ta sẽ đi vào những ví dụ và đoạn mã cụ thể để tìm hiểu Python hoạt động trên Unicode như thế nào.

1. Các hàm dựng sẵn và Unicode

Lấy 1 ví dụ đơn giản sau :

s = "Lưu Tuấn Anh"

print s, len(s)

Kết quả nhận được sẽ là :

Lưu Tuấn Anh 15

Điều này khá kì quặc khi chuỗi “Lưu Tuấn Anh” chỉ có 12 chữ cái.

Ta tiếp tục thêm vào đoạn mã sau :

for char in s:

               print char

Kết quả nhận được sẽ là :

L

u

T

u

n

A

n

h

Như vậy ta có thể thấy chữ “ư” được biểu diễn bằng 2 byte, chữ “ấ” được biểu diễn bằng 3 byte. Lý do cho lỗi phát sinh này là sự không tương thích về định dạng giữa chuỗi s và hàm len(s). Khi chuỗi s đưa vào hàm len(), nó sẽ được mặc định là ASCII, và 1 kí tự ASCII chỉ chiếm 1 byte.

Sửa lại ví dụ trên 1 chút :

s = u"Lưu Tuấn Anh"

print s, len(s)

Kết quả sẽ được :

Lưu Tuấn Anh 12

Chữ cái ‘u’ trước chuỗi là dạng viết tắt để Python hiểu được chuỗi s sẽ được hiển thị và thao tác dưới dạng Unicode. Như thế hàm len() cũng hoạt động 1 cách chính xác.

Khi lập trình xử lý tiếng Việt, chúng ta sẽ còn gặp lại nhiều tình huống giống như thế này. Vì thế bất cứ lúc nào, bạn cũng phải xác định được mình đang thao tác với chuỗi có định dạng gì : Unicode, ASCII, hay UTF8, …

2. Các toán tử với chuỗi :

Ta có đoạn code sau :

s = "Lưu "

t = s+u"Tuấn Anh"

print t, len(t), type(t)

Chuỗi s không được khai báo là Unicode, vì thế trong phép cộng 2 chuỗi ở lệnh tiếp theo, ta có dạng “1 chuỗi không phải Unicode” + “1 chuỗi là Unicode”.

Kết quả sẽ được :

Lưu Tuấn Anh 12

Ta rút ra kết luận, Python đã tự chuyển chuỗi không phải Unicode thành Unicode rồi thực hiện phép cộng, do đó chuỗi kết quả nhận được cũng dưới dạng Unicode.

Ta sẽ thử với các hàm khác trong Python :

t = "Lưu Tuấn Anh"

tt = t.split(u" ")

print tt

Kết quả sẽ khiến bạn đau đầu :

[u'L\u01b0u', u'Tu\u1ea5n', u'Anh']

Nhưng nếu chú ý kĩ, mỗi phần tử trong tt vẫn theo định dạng Unicode. Ta sẽ thêm vào đoạn mã trên 2 dòng lệnh nữa :

for tp in tt:

    print tp, len (tp)

Kết quả lúc này sẽ nhận được :

Lưu 3

Tuấn 4

Anh 3

Như thế hàm split() vẫn đảm bảo tính chính xác của chuỗi dưới dạng unicode.

Các thao tác với chuỗi khác như join, find, … cũng tương tự : khi có 1 tham số dạng Unicode thì các tham số còn lại cũng tự động chuyển sang dạng Unicode trước khi thao tác.

Tiếp tục thử với hàm upper(). Ta có đoạn mã sau :

t = "Lưu Tuấn Anh"

print t.upper()

Kết quả nhận được sẽ là :

LưU TUấN ANH

Tức là hàm upper() không tác động được lên kí tự ‘ư’ và kí tự ‘ấ’. Ta sẽ sửa lại đoạn mã trên bằng cách khai báo t dưới dạng unicode :

t = u"Lưu Tuấn Anh"

print t.upper()

Kết quả là :

LƯU TUẤN ANH

ð  Kết luận : khi thao tác trên tiếng Việt hay các chuỗi Unicode, để tránh những lỗi phát sinh không đáng có, hãy khai báo định dạng chuỗi là unicode ngay từ đầu.

Có 1 cách xử lý khác cho  vấn đề này là khai báo từ đầu chương trình : 

import sys

sys.stdout = codecs.getwriter('utf_8')(sys.stdout)

sys.stdin = codecs.getreader('utf_8')(sys.stdin)