PYTHON NÂNG CAO
Khái niệm hướng đối tượng trong Python
Python là một ngôn ngữ lập trình hướng đối tượng. Do đó với những bạn đã học qua C++ chắc rằng đã khá quen thuộc với các khái niệm về hướng đối tượng này. Chương này sẽ trình bày sơ qua về các thuật ngữ liên quan đến hướng đối tượng cùng với các ví dụ minh họa giúp bạn dễ hiểu hơn về vấn đề đã trình bày.
Một số khái niệm hướng đối tượng
- Lớp: Một nguyên mẫu được định nghĩa bởi người dùng cho một đối tượng mà định nghĩa một tập hợp các thuộc tính mà xác định rõ bất kỳ đối tượng nào của lớp đó. Các thuộc tính là các thành viên dữ liệu (các biến class và biến instance) và các phương thức được truy cập thông qua toán tử dot (dấu chấm .).
- Biến class: Đây là một biến được chia sẻ bởi tất cả các instance (sự thể hiện) của một lớp. Các biến class được định nghĩa bên trong một lớp nhưng ở bên ngoài bất cứ phương thức nào của lớp đó. Biến class không được sử dụng thường xuyên như biến instance.
- Thành viên dữ liệu: Là một biến class hoặc biến instance mà giữ dữ liệu được liên kết với một lớp và các đối tượng của nó.
- Nạp chồng hàm (overloading): Là phép gán của nhiều hơn một hành vi tới một hàm cụ thể. Hoạt động được thực hiện là đa dạng do các kiểu của các đối tượng hoặc tham số liên quan.
- Biến instance: Là một biến được định nghĩa bên trong một phương thức và chỉ thuộc sở hữu của instance hiện tại của một lớp đó.
- Tính kế thừa: Là việc truyền các đặc trưng của một lớp cho các lớp khác mà kế thừa từ lớp ban đầu.
- Instance: Là một đối tượng riêng của một lớp nào đó. Một đối tượng obj mà thuộc một lớp Circle là một instance (sự thể hiện) của lớp Circle.
- Trình khởi tạo: Là trình tạo một sự thể hiện của một lớp.
- Phương thức: Một loại hàm đặc biệt mà được định nghĩa trong một phần định nghĩa lớp.
- Đối tượng: Một instance duy nhất của một cấu trúc dữ liệu mà được định nghĩa bởi lớp của nó. Một đối tượng gồm các thành viên dữ liệu (biến class và biến instance) và các phương thức.
- Nạp chồng toán tử: Là phép gán của nhiều hơn một hàm cho một toán tử cụ thể.
Tạo các lớp trong Python
Trong Python, lệnh class được sử dụng để tạo một lớp mới. Tên của lớp theo ngay sau từ khóa class và được theo sau bởi dấu hai chấm, như sau:
class TenLop:
'Phan documentation string cho lop la tuy y'
class_suite
- Lớp có một Documentation String mà có thể được truy cập thông qua __doc__.
- class_suite gồm tất cả các lệnh thành phần mà định nghĩa các thành viên lớp, cấu trúc dữ liệu và hàm.
Dưới đây là ví dụ đơn giản về một lớp trong Python:
class Sinhvien:
'Class co so chung cho tat ca sinh vien'
svCount = 0
def __init__(self, ten, hocphi):
self.ten = ten
self.hocphi = hocphi
Sinhvien.svCount += 1
def displayCount(self):
print "Tong so Sinh vien %d" % Sinhvien.svCount
def displaySinhvien(self):
print "Ten : ", self.ten, ", Hoc phi: ", self.hocphi
- Biến svCount là một biến class có giá trị được chia sẻ trong tất cả instance của lớp Sinhvien này. Biến này có thể được truy cập dưới dạng Sinhvien.svCount từ bên trong lớp hoặc bên ngoài lớp.
- Phương thức đầu tiên __init__() là một phương thức đặc biệt, là constructor của lớp hoặc phương thức khởi tạo mà Python gọi khi bạn tạo một instance mới của lớp này.
- Bạn khai báo các phương thức khác như các hàm thông thường với exception là tham số đầu tiên cho mỗi phương thức là self. Python thêm tham số self tới List cho bạn; bạn không cần bao nó khi bạn gọi các phương thức.
Tạo Instance trong Python
Để tạo các instance của một lớp, bạn gọi lớp này bởi sử dụng tên lớp và truyền vào bất kỳ tham số nào mà phương thức __init__ của nó chấp nhận. Bạn theo dõi ví dụ sau:
"Lenh nay tao doi tuong dau tien cua lop Sinhvien"
sv1 = Sinhvien("Hoang", 4000000)
"Lenh nay tao doi tuong thu hai cua lop Sinhvien"
sv2 = Sinhvien("Huong", 4500000)
Truy cập các thuộc tính trong Python
Bạn truy cập các thuộc tính của đối tượng bởi sử dụng toán tử dot (dấu chấm) với đối tượng. Biến class sẽ được truy cập bởi sử dụng tên lớp như sau:
sv1.displaySinhvien()
sv2.displaySinhvien()
print "Tong so Sinh vien %d" % Sinhvien.svCount
Bây giờ đặt tất cả khái niệm cùng với nhau:
class Sinhvien:
'Class co so chung cho tat ca sinh vien'
svCount = 0
def __init__(self, ten, hocphi):
self.ten = ten
self.hocphi = hocphi
Sinhvien.svCount += 1
def displayCount(self):
print "Tong so Sinh vien %d" % Sinhvien.svCount
def displaySinhvien(self):
print "Ten : ", self.ten, ", Hoc phi: ", self.hocphi
"Lenh nay tao doi tuong dau tien cua lop Sinhvien"
sv1 = Sinhvien("Hoang", 4000000)
"Lenh nay tao doi tuong thu hai cua lop Sinhvien"
sv2 = Sinhvien("Huong", 4500000)
sv1.displaySinhvien()
sv2.displaySinhvien()
print "Tong so Sinh vien %d" % Sinhvien.svCount
Khi code trên được thực thi sẽ cho kết quả:
Ten : Hoang ,Hoc phi: 4000000
Ten : Huong ,Hoc phi: 4500000
Tong so Sinh vien 2
Bạn có thể thêm, xóa, hoặc sửa đổi các thuộc tính của các lớp và đối tượng tại bất cứ thời điểm nào.
sv1.tuoi = 21 # Them mot thuoc tinh 'tuoi'.
sv1.tuoi = 20 # Sua doi thuoc tinh 'tuoi'.
del sv1.tuoi # Xoa thuoc tinh 'tuoi'.
Thay vì sử dụng các lệnh chính thức để truy cập các thuộc tính, bạn có thể sử dụng các hàm sau:
- Hàm getattr(obj, name[, default]): Để truy cập thuộc tính của đối tượng.
- Hàm hasattr(obj,name): Để kiểm tra xem một thuộc tính có tồn tại hay không.
- Hàm setattr(obj,name,value): Để thiết lập một thuộc tính. Nếu thuộc tính không tồn tại, thì nó sẽ được tạo.
- Hàm delattr(obj, name): Để xóa một thuộc tính.
Ví dụ:
hasattr(sv1, 'tuoi') # Tra ve true neu thuoc tinh 'tuoi' ton tai
getattr(sv1, 'tuoi') # Tra ve gia tri cua thuoc tinh 'tuoi'
setattr(sv1, 'tuoi', 20) # Thiet lap thuoc tinh 'tuoi' la 20
delattr(sv1, 'tuoi') # Xoa thuoc tinh 'tuoi'
Các thuộc tính đã có sẵn cho lớp trong Python
Mỗi lớp Python đều giữ các thuộc tính đã được xây dựng sẵn sau và chúng có thể được truy cập bởi sử dụng toán tử dot (dấu chấm .) như bất kỳ thuộc tính khác:
- __dict__:Là Dictionary chứa namespace của lớp.
- __doc__:Được sử dụng để truy cập Documentation String của lớp nếu có.
- __name__:Là tên lớp.
- __module__:Là tên Module trong đó lớp được định nghĩa. Thuộc tính là __main__ trong chế độ tương tác.
- __bases__:Là một Tuple chứa các lớp cơ sở.
Với lớp Sinhvien trên, chúng ta sẽ thử truy cập tất cả các thuộc tính này.
class Sinhvien:
'Class co so chung cho tat ca sinh vien'
svCount = 0
def __init__(self, ten, hocphi):
self.ten = ten
self.hocphi = hocphi
Sinhvien.svCount += 1
def displayCount(self):
print "Tong so Sinh vien %d" % Sinhvien.svCount
def displaySinhvien(self):
print "Ten : ", self.ten, ", Hoc phi: ", self.hocphi
print "Sinhvien.__doc__:", Sinhvien.__doc__
print "Sinhvien.__name__:", Sinhvien.__name__
print "Sinhvien.__module__:", Sinhvien.__module__
print "Sinhvien.__bases__:", Sinhvien.__bases__
print "Sinhvien.__dict__:", Sinhvien.__dict__
Khi code trên được thực thi sẽ cho kết quả:
Sinhvien.__doc__: Class co so chung cho tat ca sinh vien
Sinhvien.__name__: Sinhvien
Sinhvien.__module__: __main__
Sinhvien.__bases__: ()
Sinhvien.__dict__: {'__module__': '__main__', 'displayCount':
<function displayCount at 0xb7c84994>, 'svCount': 2,
'displaySinhvien': <function displaySinhvien at 0xb7c8441c>,
'__doc__': 'Class co so chung cho tat ca sinh vien',
'__init__': <function __init__ at 0xb7c846bc>}
Hủy đối tượng (Trình dọn rác) trong Python
Python sẽ hủy các đối tượng mà không cần đến nữa (các kiểu đã được xây dựng sẵn hoặc instance của lớp) một cách tự động để giải phóng không gian bộ nhớ. Tiến trình này được gọi là Garbage Collection được thực hiện bởi trình dọn rác Garbage Collector.
Trình dọn rác của Python chạy trong khi thực thi chương trình và được kích hoạt khi số tham chiếu của một đối tượng tiến về 0. Số tham chiếu của một đối tượng thay đổi khi số alias mà trỏ tới nó thay đổi.
Số tham chiếu của một đối tượng tăng khi nó được gán một tên mới hoặc được đặt trong một container (chẳng hạn như List, Tuple, Dictionary). Số tham chiếu của một đối tượng giảm khi nó bị xóa với lệnh del, tham chiếu của nó được tái gán, hoặc tham chiếu của nó thoát ra khỏi phạm vi. Khi số tham chiếu của một đối tượng tiến về 0, thì Python thu thập nó một cách tự động. Ví dụ:
a = 40 # Tao doi tuong <40>
b = a # Tang so tham chieu cua <40>
c = [b] # Tang so tham chieu cua <40>
del a # Giam so tham chieu cua <40>
b = 100 # Giam so tham chieu cua <40>
c[0] = -1 # Giam so tham chieu cua <40>
Thường thì bạn sẽ không chú ý khi trình dọn rác hủy một instance và giải phóng bộ nhớ. Nhưng một lớp có thể triển khai phương thức đặc biệt là __del__(), được gọi là một destructor, mà được triệu hồi khi instance là chuẩn bị được hủy. Phương thức này có thể được sử dụng để xóa bất kỳ nguồn bộ nhớ nào được sử dụng bởi một instance.
Ví dụ
class Point:
def __init( self, x=0, y=0):
self.x = x
self.y = y
def __del__(self):
class_name = self.__class__.__name__
print class_name, "destroyed"
pt1 = Point()
pt2 = pt1
pt3 = pt1
print id(pt1), id(pt2), id(pt3) # in id cua doi tuong
del pt1
del pt2
del pt3
Khi code trên được thực thi sẽ cho kết quả sau:
3083401324 3083401324 3083401324
Point destroyed
Ghi chú: Một cách lý tưởng nhất là bạn nên định nghĩa các lớp của bạn trong file riêng biệt, sau đó bạn nên import chúng trong file chương trình chính bởi sử dụng lệnh import.
Kế thừa lớp trong Python
Thay vì bắt đầu viết code cho một lớp mới, bạn có thể tạo một lớp bằng việc kế thừa nó từ một lớp đã tồn tại trước đó bằng cách liệt kê lớp cha trong cặp dấu ngoặc đơn sau tên lớp mới.
Lớp con kế thừa các thuộc tính của lớp cha của nó, và bạn có thể sử dụng các thuộc tính như thể là chúng đã được định nghĩa trong lớp con đó. Một lớp con cũng có thể ghi đè các thành viên dữ liệu và các phương thức từ lớp cha.
Cú pháp
Các lớp kế thừa được khai báo khá giống như lớp cha của nó; tuy nhiên, một danh sách lớp cơ sở để kế thừa từ đó được cung cấp sau tên lớp mới.
class Tenlopcon (LopCha1[, LopCha2, ...]):
'Phan documentation string cua Class la tuy y'
class_suite
VÍ DỤ
class Parent: # dinh nghia lop cha
parentAttr = 100
def __init__(self):
print "Goi constructor cua lop cha"
def parentMethod(self):
print 'Goi phuong thuc cua lop cha'
def setAttr(self, attr):
Parent.parentAttr = attr
def getAttr(self):
print "Thuoc tinh cua lop cha :", Parent.parentAttr
class Child(Parent): # dinh nghia lop con
def __init__(self):
print "Goi constructor cua lop con"
def childMethod(self):
print 'Goi phuong thuc cua lop con'
c = Child() # instance cua lop con
c.childMethod() # lop con goi phuong thuc cua no
c.parentMethod() # goi phuong thuc cua lop cha
c.setAttr(200) # tiep tuc goi phuong thuc cua lop cha
c.getAttr() # tiep tuc goi phuong thuc cua lop cha
Khi code trên được thực thi sẽ cho kết quả sau:
Goi constructor cua lop con
Goi phuong thuc cua lop con
Goi phuong thuc cua lop cha
Thuoc tinh cua lop cha : 200
Theo cách tương tự, bạn có thể kế thừa một lớp từ nhiều lớp cha như sau:
class A: # dinh nghia lop A
.....
class B: # dinh nghia lop B
.....
class C(A, B): # lop con cua A va B
.....
Bạn có thể sử dụng các hàm issubclass() hoặc isinstance() để kiểm tra mối quan hệ của hai lớp và instance.
- Hàm issubclass(sub, sup)trả về true nếu lớp con sub đã cho thực sự là lớp con của lớp cha sup.
- Hàm isinstance(obj, Class)trả về true nếu obj là một instance của lớp Class hoặc là một instance của lớp con của Class.
Ghi đè phương thức trong Python
Bạn có thể ghi đè các phương thức của lớp cha. Một trong các lý do để thực hiện việc ghi đè phương thức của lớp cha là bạn muốn có tính năng khác biệt hoặc đặc biệt trong lớp con.
Ví dụ
class Parent: # dinh nghia lop cha
def myMethod(self):
print 'Goi phuong thuc cua lop cha'
class Child(Parent): # dinh nghia lop con
def myMethod(self):
print 'Goi phuong thuc cua lop con'
c = Child() # instance cua lop con
c.myMethod() # lop con goi phuong thuc duoc ghi de
Kết quả là:
Goi phuong thuc cua lop con
Nạp chồng phương thức trong Python
Bảng dưới đây liệt kê một số tính năng chung mà bạn có thể ghi đè trong các lớp riêng của bạn.
STT |
Phương thức, Miêu tả và Lời gọi mẫu |
1 |
__init__ ( self [,args...] ) |
2 |
__del__( self ) |
3 |
__repr__( self ) |
4 |
__str__( self ) |
5 |
__cmp__ ( self, x ) |
Nạp chồng toán tử trong Python
Giả sử bạn đã tạo một lớp Vector để biểu diễn các vector hai chiều. Điều gì xảy ra khi bạn sử dụng toán tử cộng (+) để cộng chúng? Có thể nói vui rằng, lúc đó Python sẽ la hét vào mặt bạn.
Tuy nhiên, bạn có thể định nghĩa phương thức __add_ trong lớp của bạn để thực hiện phép cộng vector và sau đó phép cộng vector sẽ vận hành như bạn mong đợi.
Ví dụ
class Vector:
def __init__(self, a, b):
self.a = a
self.b = b
def __str__(self):
return 'Vector (%d, %d)' % (self.a, self.b)
def __add__(self,other):
return Vector(self.a + other.a, self.b + other.b)
v1 = Vector(2,10)
v2 = Vector(5,-2)
print v1 + v2
Kết quả là:
Vector(7,8)
Ẩn dữ liệu (Data Hiding) trong Python
Các thuộc tính của một đối tượng có thể hoặc không thể là nhìn thấy với bên ngoài phần định nghĩa lớp. Bạn cần đặc tên các thuộc tính với một tiền tố là hai dấu gạch dưới, và sau đó các thuộc tính này sẽ không là nhìn thấy với bên ngoài.
Ví dụ
class JustCounter:
__secretCount = 0
def count(self):
self.__secretCount += 1
print self.__secretCount
counter = JustCounter()
counter.count()
counter.count()
print counter.__secretCount
Kết quả là:
1
2
Traceback (most recent call last):
File "test.py", line 12, in <module>
print counter.__secretCount
AttributeError: JustCounter instance has no attribute '__secretCount'
Python bảo vệ các thành viên đó bằng cách thay đổi nội tại tên để bao tên lớp. Bạn có thể truy cập các thuộc tính này dưới dạng như doi_tuong._tenLop__tenThuocTinh. Nếu bạn thay thế dòng cuối cùng như sau, thì nó sẽ làm việc cho bạn.
.........................
print counter._JustCounter__secretCount
Kết quả là:
1
2
2
Regular Expression trong Python
Một Regular Expression là một dãy ký tự đặc biệt giúp bạn so khớp hoặc tìm các chuỗi khác hoặc tập hợp các chuỗi, bởi sử dụng một cú pháp riêng trong một pattern. Regular Expression được sử dụng phổ biến trong thế giới UNIX.
re Module cung cấp sự hỗ trợ đầy đủ các Perl-like Regular Expression trong Python. Module này tạo Exception là re.error nếu xảy ra một lỗi trong khi biên dịch hoặc khi sử dụng một Regular Expression.
Có hai hàm quan trọng sẽ được sử dụng để xử lý Regular Expression, đó là:
Hàm match trong Python
Hàm này cố gắng so khớp pattern với string với các flag tùy ý. Dưới đây là cú pháp cho hàm này.
re.match(pattern, string, flags=0)
Chi tiết về tham số:
- pattern: Đây là Regular Expression để được so khớp.
- string: Đây là chuỗi, mà sẽ được tìm kiếm để so khớp pattern tại phần đầu của chuỗi.
- flags: Bạn có thể xác định các flag khác nhau bởi sử dụng toán tử |. Các modifier này sẽ được liệt kê ở bảng bên dưới.
Hàm re.match trả về một đối tượng match nếu thành công và trả về None nếu thất bại. Chúng ta sử dụng hàm group(num) hoặc groups() của đối tượng match để lấy biểu thức đã được so khớp (kết nối).
- Phương thức group(num=0) trả về toàn bộ kết nối (hoặc num phân nhóm cụ thể).
- Phương thức groups() trả về tất cả các phân nhóm kết nối trong một Tuple (là trống nếu không có kết nối hay so khớp nào).
Ví dụ:
import re
line = "Hoc Python la de hon hoc Java?"
matchObj = re.match( r'(.*) la (.*?) .*', line, re.M|re.I)
if matchObj:
print "matchObj.group() : ", matchObj.group()
print "matchObj.group(1) : ", matchObj.group(1)
print "matchObj.group(2) : ", matchObj.group(2)
else:
print "Khong co ket noi!!"
Kết quả là:
matchObj.group() : Hoc Python la de hon hoc Java?
matchObj.group(1) : Hoc Python
matchObj.group(2) : de
Hàm search trong Python
Hàm này tìm kiếm cho sự xuất hiện đầu tiên của pattern bên trong string với các flags tùy ý. Dưới đây là cú pháp cho hàm search:
re.search(pattern, string, flags=0)
Các tham số được giải thích như trong hàm match.
Hàm re.search trả về một đối tượng match nếu thành công và trả về None nếu thất bại. Chúng ta sử dụng hàm group(num) hoặc groups() của đối tượng match để lấy biểu thức đã được so khớp (kết nối). Các hàm này đã được trình bày ở trên.
Ví dụ
import re
line = "Hoc Python la de hon hoc Java?";
searchObj = re.search( r'(.*) la (.*?) .*', line, re.M|re.I)
if searchObj:
print "searchObj.group() : ", searchObj.group()
print "searchObj.group(1) : ", searchObj.group(1)
print "searchObj.group(2) : ", searchObj.group(2)
else:
print "Khong tim thay!!"
Kết quả là:
searchObj.group() : Hoc Python la de hon hoc Java?
searchObj.group(1) : Hoc Python
searchObj.group(2) : de
Phân biệt match và search trong Python
Python cung cấp hai hoạt động cơ sở dựa trên Reguler Expression, đó là: match để kiểm tra chỉ một kết nối tại phần đầu của chuỗi, trong khi search tìm kiếm một kết nối ở bất cứ đâu trong chuỗi.
Ví dụ
import re
line = "Hoc Python la de hon hoc Java?";
matchObj = re.match( r'thon', line, re.M|re.I)
if matchObj:
print "match --> matchObj.group() : ", matchObj.group()
else:
print "Khong co ket noi!!"
searchObj = re.search( r'thon', line, re.M|re.I)
if searchObj:
print "search --> searchObj.group() : ", searchObj.group()
else:
print "Khong tim thay!!"
Kết quả là:
Khong co ket noi!!
search --> searchObj.group() : thon
Tìm kiếm và thay thế trong Python
Một trong những phương thức quan trọng nhất mà sử dụng với Regular Expression là sub. Dưới đây là cú pháp:
re.sub(pattern, repl, string, max=0)
Phương thức này thay thế tất cả sự xuất hiện của pattern trong string với repl. Phương thức này sẽ thay thế tất cả sự xuất hiện trừ khi bạn cung cấp tham số max. Phương thức này trả về chuỗi đã được sửa đổi.
Ví dụ
import re
phone = "01633-810-628 # Day la so dien thoai"
# Xoa cac comment
num = re.sub(r'#.*$', "", phone)
print "So dien thoai : ", num
# Xoa cac ky tu khong phai ky so
num = re.sub(r'\D', "", phone)
print "So dien thoai : ", num
Kết quả là:
So dien thoai : 01633-810-628
So dien thoai : 01633810628
Danh sách modifier trong Python
Các modifier được liệt kê dưới đây có thể được sử dụng như là các flag tùy ý cho các hàm match và search. Bạn có thể cung cấp nhiều modifier bởi sử dụng toán tử |.
Modifier |
Miêu tả |
re.I |
Thực hiện việc kết nối hoặc so khớp không phân biệt kiểu chữ |
re.L |
Thông dịch các từ theo Locale hiện tại |
re.M |
Làm cho $ kết nối với phần cuối của một dòng (mà không chỉ kết nối phần cuối của chuỗi) và làm cho ^ kết nối với phần đầu của bất cứ dòng nào (mà không chỉ kết nối phần đầu của chuỗi) |
re.S |
Làm cho dot (dấu chấm) kết nối với bất kỳ ký tự nào, bao gồm một newline (dòng mới) |
re.U |
Thông dịch các chữ cái theo bộ ký tự Unicode. Flag này ảnh hưởng tới hành vi của \w, \W, \b, \B |
re.X |
Cho phép cú pháp "cuter" regular expression. Nó bỏ qua các khoảng trống trắng whitespace (ngoại trừ bên trong một [] hoặc khi được tránh bởi \) và coi # dưới dạng một comment |
Các Pattern trong Python
Ngoại trừ các ký tự điều khiển, (+ ? . * ^ $ ( ) [ ] { } | \), thì tất cả ký tự còn lại sẽ kết nối với chính chúng. Bạn có thể tránh một ký tự điều khiển bằng cách đặt trước nó một dấu \.
Dưới đây là danh sách các pattern có sẵn trong Python:
Pattern |
Miêu tả |
^ |
Dưới đây là danh sách các pattern có sẵn trong Python: |
$ |
Kết nối với phần cuối của dòng |
. |
Kết nối bất kỳ ký tự đơn nào ngoại trừ newline (dòng mới). Sử dụng tùy chọn m cho phép nó kết nối với newline (dòng mới) |
[...] |
Kết nối với bất kỳ ký tự đơn nào trong [] |
[^...] |
Kết nối với bất kỳ ký tự đơn nào không ở trong [] |
re* |
Kết nối với 0 hoặc nhiều sự xuất hiện của biểu thức đặt trước |
re+ |
Kết nối với 1 hoặc nhiều sự xuất hiện của biểu thức đặt trước |
re? |
Kết nối với 0 hoặc 1 sự xuất hiện của biểu thức đặt trước |
re{ n} |
Kết nối với n sự xuất hiện của biểu thức đặt trước |
re{ n,} |
Kết nối với n hoặc nhiều hơn sự xuất hiện của biểu thức đặt trước |
re{ n, m} |
Kết nối với ít nhất n và nhiều nhất m sự xuất hiện của biểu thức đặt trước |
a| b |
Kết nối với a hoặc b |
(re) |
Nhóm các Regular Expression và ghi nhớ text đã kết nối |
(?imx) |
Bật toggle tạm tời các tùy chọn i, m hoặc x bên trong một Regular Expression. Nếu trong cặp dấu ngoặc đơn thì chỉ khu vực đó bị ảnh hưởng |
(?-imx) |
Tắt toggle tạm tời các tùy chọn i, m hoặc x bên trong một Regular Expression. Nếu trong cặp dấu ngoặc đơn thì chỉ khu vực đó bị ảnh hưởng |
(?: re) |
Nhóm các Regular Expression mà không ghi nhớ text đã kết nối |
(?imx: re) |
Bật toggle tạm thời các tùy chọn i, m, hoặc x bên trong cặp dấu ngoặc đơn |
(?-imx: re) |
Tắt toggle tạm thời các tùy chọn i, m, hoặc x bên trong cặp dấu ngoặc đơn |
(?#...) |
Comment |
(?= re) |
Xác định vị trí bởi sử dụng một pattern. Không có một dãy giá trị |
(?! re) |
Xác định vị trí bởi sử dụng sự phủ định pattern. Không có một dãy giá trị |
(?> re) |
Kết nối pattern độc lập mà không backtrack |
\w |
Kết nối các ký tự từ |
\W |
Kết nối các ký tự không phải là từ |
\s |
Kết nối với whitespace. Tương đương với [\t\n\r\f] |
\S |
Kết nối với các ký tự không là whitespace |
\d |
Kết nối với các chữ số. Tương đương với [0-9] |
\D |
Kết nối với các ký tự không là chữ số |
\A |
Kết nối với phần đầu của chuỗi |
\Z |
Kết nối với phần cuối của chuỗi. Nếu một newline (dòng mới) tồn tại, nó kết nối với phần ở trước newline (dòng mới) |
\z |
Kết nối với phần cuối của chuỗi |
\G |
Kết nối với điểm mà tại đó kết nối cuối cùng được tìm thấy |
\b |
Kết nối với các giới hạn từ khi bên ngoài các dấu []. Kết nối với backspace (mã là 0x08) khi bên trong các dấu [] |
\B |
Kết nối với các giới hạn không phải là từ |
\n, \t, etc. |
Kết nối với newline (dòng mới), carriage return, tab, ... |
\1...\9 |
Kết nối với biểu thức con được nhóm thứ n |
\10 |
Kết nối biểu thức con được nhóm thứ n nếu nó đã kết nối. Nếu không, tham chiếu tới biểu diễn bát phân của một mã ký tự |
Ví dụ lớp ký tự trong Python
Ví dụ |
Miêu tả |
[Pp]ython |
Kết nối với "Python" hoặc "python" |
rub[ye] |
Kết nối với "ruby" hoặc "rube" |
[aeiou] |
Kết nối với bất kỳ một nguyên âm nào |
[0-9] |
Kết nối với bất kỳ chữ số nào, giống dạng [0123456789] |
[a-z] |
Kết nối với bất kỳ chữ cái thường ASCII nào |
[A-Z] |
Kết nối với bất kỳ chữ cái hoa ASCII nào |
[a-zA-Z0-9] |
Kết nối với bất kỳ cái nào ở trên |
[^aeiou] |
Kết nối với bất kỳ cái nào ở trên ngoại trừ nguyên âm |
[^0-9] |
Kết nối với bất kỳ cái nào ở trên ngoại trừ một chữ số |
Lập trình CGI trong Python
CGI (là viết tắt của Common Gateway Interface) là một tập hợp các chuẩn mà định nghĩa cách thông tin được trao đổi giữa Web Server và một Custom Script. Phiên bản CGI hiện tại là CGI/1.1.
Cấu hình Web Server
Trước khi tiến hành lập trình CGI, bạn đảm bảo rằng Web Server của bạn hỗ trợ CGI và được cấu hình để xử lý các chương trình CGI. Tất cả chương trình CGI được thực thi bởi HTTP đều được giữ trong một thư mục đã được cấu hình trước.
Thư mục này được gọi là CGI Directory và theo qui ước nó được đặt tên dạng /var/www/cgi-bin. Các CGI file có đuôi là .cgi, nhưng bạn cũng có thể giữ các file trong .py.
Theo mặc định, Linux Server được cấu hình để chạy các script trong thư mục cgi-bin trong /var/www. Nếu bạn muốn xác định bất kỳ thư mục nào khác để chạy CGI script của bạn, thì bạn comment các dòng sau trong httpd.conf file:
<Directory "/var/www/cgi-bin">
AllowOverride None
Options ExecCGI
Order allow,deny
Allow from all
</Directory>
<Directory "/var/www/cgi-bin">
Options All
</Directory>
Chương trình CGI đầu tiên
Dưới đây là một CGI script có tên là hello.py, được giữ trong thư mục /var/www/cgi-bin. Trước khi chạy, bạn cần thay đổi mode của file này bởi sử dụng chmod 755 hello.py để làm file này có thể thực thi.
print "Content-type:text/html\r\n\r\n"
print '<html>'
print '<head>'
print '<title>Lap trinh CGI trong Python</title>'
print '</head>'
print '<body>'
print '<h2>Day la chuong trinh CGI dau tien trong Python</h2>'
print '</body>'
print '</html>'
Kết quả là:
Day la chuong trinh CGI dau tien trong Python |
Đây là một Python script đơn giản để viết kết quả trên STDOUT chuẩn là màn hình. Dòng Content-type:text/html\r\n\r\n được gửi trở lại trình duyệt và nó xác định kiểu nội dung để được hiển thị trên màn hình trình duyệt.
HTTP Header
Dòng Content-type:text/html\r\n\r\n là một phần của HTTP Header mà được gửi tới trình duyệt để giúp trình duyệt hiểu nội dung cần được hiển thị. Tất cả HTTP Header sẽ là trong form sau:
HTTP Ten Truong: Noi Dung Cua Truong
Vi du
Content-type: text/html\r\n\r\n
Dưới đây là một số HTTP Header quan trọng khác mà bạn sẽ sử dụng thường xuyên trong lập trình CGI:
Header |
Miêu tả |
Content-type: |
Một chuỗi MIME định nghĩa định dạng của file được trả về. Ví dụ Content-type:text/html |
Expires: Date |
Ngày mà thông tin trở nên hết hiệu lực. Nó được sử dụng bởi trình duyệt để xác định khi nào trang cần được refresh. Một chuỗi date hợp lệ là trong định dạng 01 Jan 1998 12:00:00 GMT. |
Location: URL |
URL mà được trả về thay cho URL đã được yêu cầu. Bạn có thể sử dụng trường này để chuyển hướng một yêu cầu tới bất kỳ file nào |
Last-modified: Date |
Ngày sửa đổi cuối cùng của nguồn |
Content-length: N |
Độ dài (số byte) của dữ liệu đang được trả về. Trình duyệt sử dụng giá trị này để báo cáo thời gian download ước lượng cho một file |
Set-Cookie: String |
Thiết lập cookie được truyền thông qua String |
Các biến môi trường của CGI
Tất cả chương trình CGI có quyền truy cập tới các biến môi trường sau. Các biến này đóng một vai trò quan trọng trong khi viết bất cứ chương trình CGI nào.
Tên biến |
Miêu tả |
CONTENT_TYPE |
Kiểu dữ liệu của nội dung. Được sử dụng khi Client đang gửi nội dung đính kèm tới Server. Ví dụ: file upload |
CONTENT_LENGTH |
Độ dài của thông tin truy vấn. Chỉ có sẵn cho các yêu cầu POST |
HTTP_COOKIE |
Trả về các Cookie đã thiết lập trong dạng là cặp key/value |
HTTP_USER_AGENT |
Trường User-Agent chứa thông tin về user agent tạo yêu cầu. Đây là tên của trình duyệt web |
PATH_INFO |
Path cho CGI script |
QUERY_STRING |
Thông tin mã hóa URL được gửi với phương thức GET |
REMOTE_ADDR |
Địa chỉ IP của host từ xa mà tạo yêu cầu. Biến này hữu ích cho log và xác nhận |
REMOTE_HOST |
Tên đầy đủ của host tạo yêu cầu. Nếu thông tin này không có sẵn, thì REMOTE_ADDR có thể được sử dụng để lấy địa chỉ IP |
REQUEST_METHOD |
Phương thức được sử dụng để tạo yêu cầu. Phương thức được sử dụng phổ biên là GET và POST |
SCRIPT_FILENAME |
Path đầy đủ tới CGI script |
SCRIPT_NAME |
Tên của CGI script |
SERVER_NAME |
Tên của CGI script |
SERVER_SOFTWARE |
Tên và phiên bản của phần mềm mà Server đang chạy trên đó |
Chương trình CGI sau sẽ liệt kê tất cả các biến CGI.
import os
print "Content-type: text/html\r\n\r\n";
print "<font size=+1>Environment</font><\br>";
for param in os.environ.keys():
print "<b>%20s</b>: %s<\br>" % (param, os.environ[param])
Truyền thông tin bởi sử dụng phương thức GET
Phương thức GET gửi thông tin người dùng đã mã hóa được phụ thêm tới yêu cầu trang. Trang và thông tin mã hóa được phân biệt bởi ký tự ? như sau:
http://www.test.com/cgi-bin/hello.py?key1=value1&key2=value2
Phương thức GET là phương thức mặc định để truyền thông tin từ trình duyệt tới Web Server và nó tạo ra một chuỗi dài xuất hiện trong Location:box của trình duyệt.
Nếu bạn có password hoặc bất cú thông tin nhạy cảm nào khác cần truyền tới Server thì bạn đừng bao giờ sử dụng phương thức GET. Phương thức GET có giới hạn kích cỡ: chỉ có 1024 ký tự có thể được gửi trong một chuỗi yêu cầu. Phương thức GET gửi thông tin bởi QUERY_STRING Header và sẽ là có thể truy cập trong chương trìn CGI thông qua biến môi trường QUERY_STRING.
Bạn có thể truyền thông tin bằng cách đơn giản là nối chuỗi các cặp key và value cùng với bất cứ URL nào hoặc bạn có thể sử dụng thẻ form trong HTML.
Phương thức GET: Ví dụ URL đơn giản
URL đơn giản sau sẽ truyền hai giá trị tới chương trình hello_get.py bởi sử dụng phương thức GET.
/cgi-bin/hello_get.py?first_name=HOANG&last_name=NGUYEN
Dưới đây là hello_get.py để xử lý đầu vào đã được cung cấp bởi trình duyệt web. Chúng ta đang sử dụng cgi Module giúp cho việc truy cập thông tin đã truyền được dễ dàng hơn.
# Import cac module de xu ly CGI
import cgi, cgitb
# Tao instance cua FieldStorage
form = cgi.FieldStorage()
# Lay du lieu tu cac truong
first_name = form.getvalue('first_name')
last_name = form.getvalue('last_name')
print "Content-type:text/html\r\n\r\n"
print "<html>"
print "<head>"
print "<title>Chuong trinh CGI thu hai</title>"
print "</head>"
print "<body>"
print "<h2>Hello %s %s</h2>" % (first_name, last_name)
print "</body>"
print "</html>"
Phương thức GET: Ví dụ FORM đơn giản
Ví dụ sau sẽ truyền hai giá trị bởi sử dụng HTML form và nút submit. Chúng ta sử dụng hello_get.py giống như trên để xử lý đầu vào này.
<form action="/cgi-bin/hello_get.py" method="get">
First Name: <input type="text" name="first_name"> <br />
Last Name: <input type="text" name="last_name" />
<input type="submit" value="Submit" />
</form>
Truyền thông tin bởi sử dụng phương thức POST
Một phương thức đáng tin cậy hơn để truyền thông tin tới một chương trình CGI là phương thức POST. Phương thức này đóng gói thông tin theo đúng như cách của phương thức GET, nhưng thay vì gửi nó dưới dạng một chuỗi text sau một dấu ? trong URL, thì nó gửi dưới dạng một thông điệp riêng rẽ. Thông điệp này vào trong CGI script trong dạng đầu vào chuẩn.
Ví dụ sau cũng sử dụng hello_get.py ở trên.
# Import cac module de xu ly CGI
import cgi, cgitb
# Tao instance cua FieldStorage
form = cgi.FieldStorage()
# Lay du lieu tu cac truong
first_name = form.getvalue('first_name')
last_name = form.getvalue('last_name')
print "Content-type:text/html\r\n\r\n"
print "<html>"
print "<head>"
print "<title>Chuong trinh CGI thu hai</title>"
print "</head>"
print "<body>"
print "<h2>Hello %s %s</h2>" % (first_name, last_name)
print "</body>"
print "</html>"
Sử dụng lại ví dụ trên để truyền hai giá trị bởi sử dụng HTML form và nút submit.
<form action="/cgi-bin/hello_get.py" method="post">
First Name: <input type="text" name="first_name"><br />
Last Name: <input type="text" name="last_name" />
<input type="submit" value="Submit" />
</form>
Truyền Checkbox tới chương trình CGI
HTML code sau là cho một form với hai checkbox:
<form action="/cgi-bin/checkbox.cgi" method="POST" target="_blank">
<input type="checkbox" name="toan" value="on" /> Toan
<input type="checkbox" name="vatly" value="on" /> VatLy
<input type="submit" value="Chon Mon Hoc" />
</form>
Dưới đây là checkbox.cgi để xử lý đầu vào được cung cấp bởi trình duyệt web:
# Import cac module de xu ly CGI
import cgi, cgitb
# Tao instance cua FieldStorage
form = cgi.FieldStorage()
# Lay du lieu tu cac truong
if form.getvalue('toan'):
toan_flag = "ON"
else:
toan_flag = "OFF"
if form.getvalue('vatly'):
vatly_flag = "ON"
else:
vatly_flag = "OFF"
print "Content-type:text/html\r\n\r\n"
print "<html>"
print "<head>"
print "<title>Vi du Checkbox</title>"
print "</head>"
print "<body>"
print "<h2> Mon Toan la : %s</h2>" % toan_flag
print "<h2> Mon Vat Ly la : %s</h2>" % vatly_flag
print "</body>"
print "</html>"
Truyền RadioButton tới chương trình CGI
HTML code sau cho một form với hai Radiobutton:
<form action="/cgi-bin/radiobutton.py" method="post" target="_blank">
<input type="radio" name="subject" value="toan" /> Toan
<input type="radio" name="subject" value="vatly" /> VatLy
<input type="submit" value="Chon Mon Hoc" />
</form>
Và đây là radiobutton.py để xử lý đầu vào được cung cấp bởi trình duyệt web:
# Import cac module de xu ly CGI
import cgi, cgitb
# Tao instance cua FieldStorage
form = cgi.FieldStorage()
# Lay du lieu tu cac truong
if form.getvalue('subject'):
subject = form.getvalue('subject')
else:
subject = "Khong duoc thiet lap"
print "Content-type:text/html\r\n\r\n"
print "<html>"
print "<head>"
print "<title>Vi du Radio button</title>"
print "</head>"
print "<body>"
print "<h2> Mon hoc ban da chon la %s</h2>" % subject
print "</body>"
print "</html>"
VÍ DỤ FILE UPLOAD
Để upload một file, HTML form phải có thuộc tính enctype được thiết lập thành multipart/form-data.
<html>
<body>
<form enctype="multipart/form-data"
action="save_file.py" method="post">
<p>File: <input type="file" name="filename" /></p>
<p><input type="submit" value="Upload" /></p>
</form>
</body>
</html>
Dưới đây là save_file.py để xử lý file upload:
import cgi, os
import cgitb; cgitb.enable()
form = cgi.FieldStorage()
# Lay ten file o day.
fileitem = form['filename']
# Kiem tra xem file da duoc upload chua
if fileitem.filename:
fn = os.path.basename(fileitem.filename)
open('/tmp/' + fn, 'wb').write(fileitem.file.read())
message = 'File co ten la "' + fn + '" duoc upload thanh cong'
else:
message = 'Khong co file nao duoc upload'
print """\
Content-Type: text/html\n
<html>
<body>
<p>%s</p>
</body>
</html>
""" % (message,)
Sử dụng Cookie
Cookie là bản ghi dữ liệu thuần text của 5 trường biến sau:
- Expires:Ngày cookie sẽ hết hạn. Nếu là trống, thì cookie sẽ hết hạn khi khách truy cập thoát khỏi trình duyệt.
- Domain:Tên miền của site của bạn.
- Path:Path tới thuc mục hoặc trang web mà thiết lập cookie. Nó có thể là trống nếu bạn muốn thu nhận cookie từ bất kỳ thư mục hoặc trang nào.
- Secure:Nếu trường này chứa từ secure, thì cookie có thể chỉ được thu nhận bởi một server an toàn. Nếu để trống, thì không tồn tại giới hạn nào.
- Name=Value:Cookie được thiết lập và thu nhận trong dạng các cặp key-value.
Thiết lập cookie
Để gửi cookie tới trình duyệt là khá dễ dàng. Các cookie này được gửi cùng với HTTP Header, ở trước trường Content-type. Giả sử bạn muốn thiết lập UserID và Password là các cookie, thì việc này được thực hiện như sau:
print "Set-Cookie:UserID=XYZ;\r\n"
print "Set-Cookie:Password=XYZ123;\r\n"
print "Set-Cookie:Expires=Tuesday, 31-Nov-2015 23:12:40 GMT";\r\n"
print "Set-Cookie:Domain=www.vietjack.com;\r\n"
print "Set-Cookie:Path=/perl;\n"
print "Content-type:text/html\r\n\r\n"
...........Rest of the HTML Content....
Qua ví dụ trên, bạn có thể thấy rằng chúng ta đã sử dụng trường Set-Cookie để thiết lập các cookie. Việc thiết lập các thuộc tính của cookie như Expires, Domain, Path là tùy ý. Bạn cần chú ý là các cookie được thiết lập trước khi gửi trường "Content-type:text/html\r\n\r\n.
Thu nhận Cookie
Để thu nhận tất cả các Cookie đã thiết lập là khá dễ dàng. Các cookie được lưu trữ trong biến môi trường HTTP_COOKIE của CGI và có dạng sau:
key1=value1;key2=value2;key3=value3....
Dưới đây là ví dụ đơn giản minh họa cách thu nhận các cookie:
# Import cac module de xu ly CGI
from os import environ
import cgi, cgitb
if environ.has_key('HTTP_COOKIE'):
for cookie in map(strip, split(environ['HTTP_COOKIE'], ';')):
(key, value ) = split(cookie, '=');
if key == "UserID":
user_id = value
if key == "Password":
password = value
print "Ten dang nhap = %s" % user_id
print "Mat khau = %s" % password
Truy cập MySQL Database trong Python
Chương này sẽ giới thiệu khái quát cho bạn về cách truy cập Database bởi sử dụng Python và giới thiệu qua về một số hoạt động cơ bản trên Database như INSERT, UPDATE, DELETE ...
Trước khi theo dõi và thực hành chương này, bạn cần phải tải một DB API Module riêng cho mỗi Database bạn cần truy cập. DB API cung cấp một chuẩn tối thiểu để làm việc với Database bởi sử dụng Python. Trong chương này, chúng ta sẽ sử dụng MySQL, vì thế trước hết chúng ta hãy tìm hiểu qua về MySQLdb Module.
MySQLdb là gì?
MySQLdb là một Interface để kết nối tới một MySQL Database Server từ Python. Nó triển khai Python Database API 2.0 và được xây dựng trên cùng của MySQL C API.
Cách cài đặt MySQLdb?
Trước khi tiến hành, bạn cần cài đặt MySQL trên thiết bị của bạn. Sau đó gõ dòng Python script sau và thực thi nó:
import MySQLdb
Nếu nó cho kết quả sau, thì nghĩa là MySQLdb Module đã không được cài đặt:
Traceback (most recent call last): File "test.py", line 3, in <module> import MySQLdbImportError: No module named MySQLdb
Để cài đặt MySQLdb Module, tải nó từ MySQLdb Download và tiến hành như sau:
$ gunzip MySQL-python-1.2.2.tar.gz$ tar -xvf MySQL-python-1.2.2.tar$ cd MySQL-python-1.2.2$ python setup.py build$ python setup.py install
Kết nối Database trong Python
Trước khi kết nối với một MySQL Database, đảm bảo:
- Bạn đã tạo một Database có tên là TESTDB.
- Bạn đã tạo một bảng là SINHVIEN trong TESTDB.
- Bảng này có các trường HO, TEN, TUOI, GIOITINH và HOCPHI
- User ID là testuser và password là test123 được thiết lập để truy cập TESTDB.
- MySQLdb Module được cài đặt phù hợp trên thiết bị của bạn.
- Bạn đã hiểu cơ bản về MySQL, nếu chưa, bạn có thể tham khảo Bài hướng dẫn MySQL.
Dưới đây là ví dụ về kết nối với TESTDB.
import MySQLdb
# mo ket noi toi Database
db = MySQLdb.connect("localhost","testuser","test123","TESTDB" )
# chuan bi mot doi tuong cursor boi su dung phuong thuc cursor()
cursor = db.cursor()
# Thuc thi truy van SQL boi su dung phuong thuc execute().
cursor.execute("SELECT VERSION()")
# Lay mot hang boi su dung phuong thuc fetchone().
data = cursor.fetchone()
print "Database version : %s " % data
# ngat ket noi voi server
db.close()
Khi chạy script này, nó sẽ cho kết quả sau trên thiết bị Linux.
Database version : 5.0.45
Nếu một kết nối được thành lập, thì một đối tượng Connection được trả về và được lưu giữ vào trong db, nếu không db được thiết lập là None. Tiếp đó, đối tượng db được sử dụng để tạo đối tượng cursor, mà tiếp đó được sử dụng để thực thi các truy vấn SQL. Cuối cùng, trước khi thoát ra, nó bảo đảm rằng kết nối tới Database được đóng và các resource được giải phóng.
Tạo bảng dữ liệu trong Python
Khi một kết nối tới Database đã được thành lập, chúng ta có thể tạo các bảng hoặc bản ghi vào trong bảng đó bởi sử dụng phương thức execute của đối tượng cursor đã được tạo.
Bạn theo dõi ví dụ để tạo bảng SINHVIEN:
import MySQLdb
# mo ket noi toi Database
db = MySQLdb.connect("localhost","testuser","test123","TESTDB" )
# chuan bi mot doi tuong cursor boi su dung phuong thuc cursor()
cursor = db.cursor()
# Xoa bang neu no da ton tai boi su dung phuong thuc execute().
cursor.execute("DROP TABLE IF EXISTS SINHVIEN")
# Tao mot bang
sql = """CREATE TABLE SINHVIEN (
HO CHAR(20) NOT NULL,
TEN CHAR(20),
TUOI INT,
GIOITINH CHAR(1),
HOCPHI FLOAT )"""
cursor.execute(sql)
# ngat ket noi voi server
db.close()
Hoạt động INSERT trong Python
Đây là hoạt động bắt buộc khi bạn muốn tạo các bản ghi vào trong bảng đã tạo.
Ví dụ sau sẽ thực thi lệnh SQL INSERT để tạo một bản ghi vào trong bảng SINHVIEN.
import MySQLdb
# mo ket noi toi Database
db = MySQLdb.connect("localhost","testuser","test123","TESTDB" )
# chuan bi mot doi tuong cursor boi su dung phuong thuc cursor()
cursor = db.cursor()
# Truy van SQL de INSERT mot ban ghi vao trong database.
sql = """INSERT INTO SINHVIEN(HO,
TEN, TUOI, GIOITINH, HOCPHI)
VALUES ('Nguyen', 'Hoang', 20, 'M', 4000000)"""
try:
# Thuc thi lenh SQL
cursor.execute(sql)
# Commit cac thay doi vao trong Database
db.commit()
except:
# Rollback trong tinh huong co bat ky error nao
db.rollback()
# ngat ket noi voi server
db.close()
Ví dụ trên có thể được viết như sau để tạo các truy vấn SQL hay hơn:
import MySQLdb
# mo ket noi toi Database
db = MySQLdb.connect("localhost","testuser","test123","TESTDB" )
# chuan bi mot doi tuong cursor boi su dung phuong thuc cursor()
cursor = db.cursor()
# Truy van SQL de INSERT mot ban ghi vao trong database.
sql = "INSERT INTO SINHVIEN(HO, \
TEN, TUOI, GIOITINH, HOCPHI) \
VALUES ('%s', '%s', '%d', '%c', '%d' )" % \
('Nguyen', 'Hoang', 20, 'M', 4000000)
try:
# Thuc thi lenh SQL
cursor.execute(sql)
# Commit cac thay doi vao trong Database
db.commit()
except:
# Rollback trong tinh huong co bat ky error nao
db.rollback()
# ngat ket noi voi server
db.close()
VÍ DỤ
Đoạn code sau là form thực thi khác, tại đây bạn có thể truyền các tham số một cách trực tiếp.
..................................
user_id = "test123"
password = "password"
con.execute('chen cac gia tri de dang nhap ("%s", "%s")' % \
(user_id, password))
..................................
Hoạt động đọc trong Python
Hoạt động đọc trên bất cứ Database nào nghĩa là lấy một số thông tin hữu ích từ Database.
Khi kết nối với Databse được thiết lập, bạn có thể tạo một truy vấn vào trong Database này. Bạn có thể sử dụng hoặc phương thức fetchone() để lấy bản ghi đơn hoặc phương thức fetchall() để lấy nhiều giá trị từ một bảng.
- Hàm fetchone()lấy hàng tiếp theo của một tập kết quả truy vấn. Một tập kết quả là một đối tượng được trả về khi một đối tượng cursor được sử dụng để truy vấn một bảng.
- Hàm fetchall()lấy tất cả các hàng trong một tập kết quả. Nếu một số hàng đã sẵn sàng được trích từ tập kết quả đó, thì nó thu nhận các hàng còn lại từ tập kết quả.
- Thuộc tính rowcountlà một thuộc tính read-only và trả về số hằng đã bị ảnh hưởng bởi phương thức execute().
Ví dụ sau truy vấn tất cả bản ghi từ bảng SINHVIEN mà có salary lớn hơn 1000:
import MySQLdb
# mo ket noi toi Database
db = MySQLdb.connect("localhost","testuser","test123","TESTDB" )
# chuan bi mot doi tuong cursor boi su dung phuong thuc cursor()
cursor = db.cursor()
# Chuan bi truy van SQl de INSERT mot ban ghi vao trong database.
sql = "SELECT * FROM SINHVIEN \
WHERE HOCPHI > '%d'" % (1000)
try:
# Thuc thi lenh SQL
cursor.execute(sql)
# Lay tat ca cac hang trong list.
results = cursor.fetchall()
for row in results:
ho = row[0]
ten = row[1]
tuoi = row[2]
gioitinh = row[3]
hocphi = row[4]
# Bay gio in ket qua
print "ho=%s,ten=%s,tuoi=%d,gioitinh=%s,hocphi=%d" % \
(ho, ten, tuoi, gioitinh, hocphi )
except:
print "Error: khong lay duoc du lieu"
# ngat ket noi voi server
db.close()
Kết quả là:
ho=Nguyen, ten=Hoang, tuoi=20, gioitinh=M, hocphi=4000000
Hoạt động Update trong Python
Hoạt động UPDATE trên bất cứ Database nào nghĩa là để cập nhật một hoặc nhiều bản ghi mà đã có sẵn trong Database.
Thủ tục sau cập nhật tất cả bản ghi có GIOITINH là M. Ở đây, chúng ta tăng tất cả TUOI của male thêm 1 năm.
Ví dụ
import MySQLdb
# mo ket noi toi Database
db = MySQLdb.connect("localhost","testuser","test123","TESTDB" )
# chuan bi mot doi tuong cursor boi su dung phuong thuc cursor()
cursor = db.cursor()
# Truy van SQL de UPDATE cac ban ghi
sql = "UPDATE SINHVIEN SET TUOI = TUOI + 1
WHERE GIOITINH = '%c'" % ('M')
try:
# Thuc thi lenh SQL
cursor.execute(sql)
# Commit cac thay doi vao trong Database
db.commit()
except:
# Rollback trong tinh huong co bat ky error nao
db.rollback()
# ngat ket noi voi server
db.close()
Hoạt động DELETE trong Python
Hoạt động DELETE là cần thiết khi bạn muốn xóa một số bản ghi từ Database. Dưới đây là thủ tục để xóa tất cả bản ghi từ bảng SINHVIEN với điều kiện là TUOI lớn hơn 20:
Ví dụ
Ngắt kết nối tới Database trong Python
Để ngắt kết nối tới Database, bạn sử dụng phương thức close(), có cú pháp như sau:
Lập trình mạng trong Python
Chương này sẽ trình bày cho bạn hiểu về khái niệm quan trọng nhất trong lập trình mạng, đó là Lập trình Socket.
Socket là gì?
Socket là các điểm đầu nút (endpoint) của một kênh giao tiếp song hướng. Các Socket có thể giao tiếp bên trong một tiến trình, giữa các tiến trình trên cùng một thiết bị hoặc giữa các tiến trình trên các lục địa khác nhau.
Các Socket có thể được triển khai thông qua các kênh khác nhau: domain, TCP, UDP, … Thư viện socket cung cấp các lớp riêng để xử lý các trình truyền tải cũng như một Interface chung để xử lý phần còn lại.
Socket có các khái niệm riêng như sau:
Khái niệm |
Miêu tả |
domain |
Là family của các giao thức protocol được sử dụng như là kỹ thuật truyền tải. Các giá trị này là các hằng như AF_INET, PF_INET, PF_UNIX, PF_X25, … |
type |
Kiểu giao tiếp giữa hai endpoint, đặc trưng là SOCK_STREAM cho các giao thức hướng kêt nối (connection-oriented) và SOCK_DGRAM cho các giao thức không hướng kết nối |
protocol |
Đặc trưng là 0, mà có thể được sử dụng để nhận diện một biến thể của một giao thức bên trong một domain hoặc type |
hostname |
Định danh của một network interface:
|
port |
Mỗi Server nghe các lời gọi từ Client trên một hoặc nhiều cổng (port). Một port có thể là một chuỗi chứa số hiệu của port, một tên của một dịch vụ, … |
socket Module trong Python
Để tạo một Socket, bạn phải sử dụng hàm socket.socket() có sẵn trong socket Module, có cú pháp chung như sau:
s = socket.socket (socket_family, socket_type, protocol=0)
Chi tiết về tham số:
- socket_family:Đây hoặc là AF_UNIX hoặc AF_INET.
- socket_type:Đây hoặc là SOCK_STREAM hoặc SOCK_DGRAM.
- protocol:Thường được để trống, mặc định là 0.
Khi bạn đã có đối tượng socket, bạn có thể sử dụng các hàm để tạo chương trình cho Client hoặc Server. Dưới đây là danh sách các hàm:
Các phương thức sử dụng cho Server Socket
Phương thức |
Miêu tả |
s.bind() |
Phương thức này gắn kết địa chỉ (hostname, port number) tới Socket |
s.listen() |
Phương thức này thiết lập và bắt đầu TCP Listener. |
s.accept() |
Phương thức này chấp nhận một cách thụ động kết nối TCP Client, đợi cho tới khi kết nối tới. |
Các phương thức sử dụng cho Client Socket
s.connect(): Phương thức này khởi tạo kết nối TCP Server.
Các phương thức chung cho Socket
Phương thức |
Miêu tả |
s.recv() |
Phương thức này nhận TCP message. |
s.send() |
Phương thức này truyền TCP message. |
s.recvfrom() |
Phương thức này nhận UDP message. |
s.sendto() |
Phương thức này truyền UDP message. |
s.close() |
Phương thức này đóng Socket. |
socket.gethostname() |
Trả về hostname. |
Ví dụ viết một chương Server đơn giản trong Python
Để viết một Server, bạn sử dụng hàm socket có trong socket Module để tạo một đối tượng socket. Sau đó, đối tượng socket được sử dụng để gọi các hàm khác để thiết lập một Socket Server.
Bây giờ gọi hàm bind(hostname, port) để xác định một port cho dịch vụ của bạn trên host đã cho.
Tiếp đó, gọi phương thức accept của đối tượng được trả về. Phương thức này đợi tới khi một Client kết nối tới port mà bạn đã xác định, và sau đó trả về một đối tượng connection mà biểu diễn kết nối tới Client đó.
# Day la server.py file
import socket # Import socket module
s = socket.socket() # Tao mot doi tuong socket
host = socket.gethostname() # Lay ten thiet bi local
port = 12345 # Danh rieng mot port cho dich vu cua ban.
s.bind((host, port)) # Ket noi toi port
s.listen(5) # Doi 5 s de ket noi voi client.
while True:
c, addr = s.accept() # Thiet lap ket noi voi client.
print 'Da ket noi voi', addr
c.send('Cam on ban da ket noi')
c.close() # Ngat ket noi
Ví dụ viết một chương trình Client đơn giản trong Python
Chúng ta viết một chương trình Client đơn giản để mở một kết nối tới một port có số hiệu đã cho là 12345 và với host đã xác định.
Hàm socket.connect(hosname, port ) mở một kết nối TCP tới hostname trên port đã cho. Khi bạn có một socket đã được mở, bạn có thể đọc từ nó giống như bất kỳ đối tượng IO nào.
Code sau là một Client rất đơn giản để kết nối tới host và port đã cho, đọc bất cứ dữ liệu nào có sẵn từ Socket đó và sau đó thoát.
# This is client.py file
import socket # Import socket module
s = socket.socket() # Tao mot doi tuong socket
host = socket.gethostname() # Lay ten thiet bi local
port = 12345 # Danh rieng mot port cho dich vu cua ban.
s.connect((host, port))
print s.recv(1024)
s.close # Dong socket
Bây giờ chạy server.py trong background và sau đó chạy client.py trên để xem kết quả.
# Chay server trong background.
$ python server.py &
# Mot khi server da bat dau, ban chay client nhu sau:
$ python client.py
Kết quả là:
Da ket noi voi ('127.0.0.1', 48437)
Cam on ban da ket noi
Các Module quan trọng trong lập trình mạng
Protocol |
Tính năng chung |
Port No |
Python module |
HTTP |
Web page |
80 |
httplib, urllib, xmlrpclib |
NNTP |
Usenet new |
119 |
nntplib |
FTP |
Truyền tải file |
20 |
ftplib, urllib |
SMTP |
Gửi email |
25 |
smtplib |
POP3 |
Lấy email |
110 |
poplib |
IMAP4 |
Lấy email |
143 |
imaplib |
Telnet |
Command line |
23 |
telnetlib |
Gopher |
Truyền tải Document |
70 |
gopherlib, urllib |
Gửi Email sử dụng SMTP trong Python
SMTP (là viết tắt của Simple Mail Transfer Protocol) là một giao thức để xử lý trình gửi và định tuyến email giữa các Mail Server. Python cung cấp smtplib Module, mà định nghĩa một đối tượng SMTP Client Session có thể được sử dụng để gửi email tới bất kỳ thiết bị internet nào với một SMTP hoặc ESMTP Listener.
Dưới đây là cú pháp cơ bản để tạo một đối tượng SMTP:
import smtplib
smtpObj = smtplib.SMTP( [host [, port [, local_hostname]]] )
Chi tiết về tham số:
- host:Đây là host đang chạy SMTP Server của bạn. Bạn có thể xác định địa chỉ IP của host hoặc một tên miền như vietjack.com. Đây là tham số tùy ý.
- port:Nếu bạn cung cấp tham số host, thì bạn cần xác định một port, đây là nơi SMTP Server nghe yêu cầu. Thường thì port này sẽ là 25.
- ten_localhost: Nếu SMTP Server của bạn đang chạy trên thiết bị local, thì bạn có thể xác định là localhostcho tùy chọn này.
Đối tượng SMTP có một phương thức instance là sendmail, được sử dụng để gửi một thông điệp. Nó nhận ba tham số:
- sender- Là một chuỗi chỉ địa chỉ của người gửi.
- receivers- Một danh sách các chuỗi, mỗi chuỗi là địa chỉ của người nhận.
- message- Là một thông điệp dưới định dạng chuỗi.
Ví dụ
Dưới đây là cách đơn giản để gửi một email bởi sử dụng Python.
import smtplib
sender = 'from@fromdomain.com'
receivers = ['to@todomain.com']
message = """From: Tu <from@fromdomain.com>
To: Toi <to@todomain.com>
Subject: SMTP e-mail test
Day la vi du ve gui email.
"""
try:
smtpObj = smtplib.SMTP('localhost')
smtpObj.sendmail(sender, receivers, message)
print "Gui email thanh cong"
except SMTPException:
print "Error: khong the gui email"
Trong ví dụ trên, chúng ta đã đặt một email cơ bản trong message, bởi sử dụng trích dẫn tam. Bạn cần định dạng các trường header một cách chính xác. Một email cần một From, To, và Subject header, được phân biệt với phần thân email bởi một dòng trắng.
Để gửi một email, bạn sử dụng smtpObj để kết nối tới SMTP Server trên thiết bị local và sau đó sử dụng phương thức sendmail cùng với thông điệp message, địa chỉ người gửi, địa chỉ người nhận là các tham số.
Nếu bạn không chạy SMTP Server trên thiết bị local, bạn có thể sử dụng smtplib Client để giao tiếp với một SMTP Server từ xa. Ví dụ:
smtplib.SMTP('mail.your-domain.com', 25)
Gửi HTML email bởi sử dụng Python
Khi bạn gửi một text message bởi sử dụng Python, thì tất cả nội dung được xem như dưới dạng text đơn giản. Ngay cả khi bạn bao các HTML tag trong thông điệp text này, thì nó cũng chỉ hiển thị dưới dạng text đơn giản và các thẻ HTML này sẽ không được định dạng tương ứng với cú pháp HTML. Nhưng Python cung cấp tùy chọn để gửi một HTML message dưới dạng một thông điệp HTML thực sự.
Trong khi gửi một email message, bạn có thể xác định một Mine version, kiểu nội dung, và bộ ký tự để gửi một HTML email.
Ví dụ
Ví dụ đơn giản này gửi một HTML content dưới dạng một email.
import smtplib
message = """From: Tu <from@fromdomain.com>
To: Toi <to@todomain.com>
MIME-Version: 1.0
Content-type: text/html
Subject: SMTP HTML e-mail test
Day la vi du gui email trong dinh dang HTML
<b>Day la HTML message.</b>
<h1>Day la headline.</h1>
"""
try:
smtpObj = smtplib.SMTP('localhost')
smtpObj.sendmail(sender, receivers, message)
print "Gui email thanh cong"
except SMTPException:
print "Error: khong the gui email"
Gửi đính kèm với email bởi sử dụng Python
Để làm điều này, bạn cần thiết lập trường Content-type header thành multipart/mixed. Sau đó, các phần text và attachment có thể được xác định bên trong boundaries.
Một boundary được bắt đầu với hai dấu gạch nối (--) được theo sau bởi một số duy nhất, mà không thể xuất hiện trong phần thông điệp của email. Một final boundary, biểu thị khu vực cuối cùng của email đó, cũng phải kết thúc với hai dấu gạch dưới.
Các file đính kèm nên được bao quanh bởi hàm pack("m") để có mã hóa base64 trước khi truyền tải.
Ví dụ
Ví dụ sau sẽ gửi một file có tên là /tmp/test.txt dưới dạng một đính kèm.
import smtplib
import base64
filename = "/tmp/test.txt"
# Doc mot file va ma hoa no trong dinh dang base64
fo = open(filename, "rb")
filecontent = fo.read()
encodedcontent = base64.b64encode(filecontent) # base64
sender = 'webmaster@vietjack.com'
reciever = 'amrood.admin@gmail.com'
marker = "AUNIQUEMARKER"
body ="""
Day la vi du de gui email voi attachment.
"""
# Dinh nghia cac header.
part1 = """From: Tu <me@fromdomain.net>
To: Toi <amrood.admin@gmail.com>
Subject: Sending Attachement
MIME-Version: 1.0
Content-Type: multipart/mixed; boundary=%s
--%s
""" % (marker, marker)
# Dinh nghia message action
part2 = """Content-Type: text/plain
Content-Transfer-Encoding:8bit
%s
--%s
""" % (body,marker)
# Dinh nghia phan attachment
part3 = """Content-Type: multipart/mixed; name=\"%s\"
Content-Transfer-Encoding:base64
Content-Disposition: attachment; filename=%s
%s
--%s--
""" %(filename, filename, encodedcontent, marker)
message = part1 + part2 + part3
try:
smtpObj = smtplib.SMTP('localhost')
smtpObj.sendmail(sender, reciever, message)
print "Gui email thanh cong"
except Exception:
print "Error: khong the gui email"
Đa luồng (Multithread) trong Python
Một chương trình đa luồng chứa hai hoặc nhiều phần mà có thể chạy đồng thời và mỗi phần có thể xử lý tác vụ khác nhau tại cùng một thời điểm, để sử dụng tốt nhất các nguồn có sẵn, đặc biệt khi máy tính của bạn có nhiều CPU.
Python cung cấp thread Module và threading Module để bạn có thể bắt đầu một thread mới cũng như một số tác vụ khác trong khi lập trình đa luồng. Mỗi một Thread đều có vòng đời chung là bắt đầu, chạy và kết thúc. Một Thread có thể bị ngắt (interrupt), hoặc tạm thời bị dừng (sleeping) trong khi các Thread khác đang chạy – được gọi là yielding.
Bắt đầu một Thread mới trong Python
Phương thức dưới đây có sẵn trong thread Module được sử dụng để bắt đầu một Thread mới:
thread.start_new_thread ( function, args[, kwargs] )
Lời gọi phương thức này được trả về ngay lập tức và Thread con bắt đầu và gọi hàm function với danh sách các tham số args đã truyền. Khi hàm function trả về, thì Thread kết thúc.
Ở đây, args là một Tuple của các tham số, sử dụng một Tuple trống để gọi hàm function mà không truyền cho nó bất kỳ tham số nào. Tham số kwargs là một Dictionary của các tham số từ khóa tùy ý. (bạn thao khảo chương Hàm trong Python để biết chi tiết tham số từ khóa là gì)
Ví dụ
import thread
import time# Dinh nghia mot ham cho thread
def print_time( threadName, delay):
count = 0
while count < 5:
time.sleep(delay)
count += 1
print "%s: %s" % ( threadName, time.ctime(time.time()) )# Tao hai thread nhu sau
try:
thread.start_new_thread( print_time, ("Thread-1", 2, ) )
thread.start_new_thread( print_time, ("Thread-2", 4, ) )
except:
print "Error: khong the bat dau thread"while 1:
pass
Kết quả là:
Thread-1: Mon Nov 21 15:42:17 2015
Thread-1: Mon Nov 21 15:42:19 2015
Thread-2: Mon Nov 21 15:42:19 2015
Thread-1: Mon Nov 21 15:42:21 2015
Thread-2: Mon Nov 21 15:42:23 2015
Thread-1: Mon Nov 21 15:42:23 2015
Thread-1: Mon Nov 21 15:42:25 2015
Thread-2: Mon Nov 21 15:42:27 2015
Thread-2: Mon Nov 21 15:42:31 2015
Thread-2: Mon Nov 21 15:42:35 2015
Mặc dù thread Module rất hiệu quả với đa luồng tầm thấp nhưng khi so sánh với threading Module thì nó có nhiều điểm hạn chế. Phần tiếp theo giới thiệu về threading Module.
threading Module trong Python
Module mới này được bao với Python 2.4 nhằm cung cấp nhiều hỗ trợ mạnh mẽ và cấp độ cao hơn cho các Thread trong khi so sánh với thread Module ở trên. Ngoài các phương thức có trong thread Module, thì threading Module còn bổ sung thêm một số phương thức khác, đó là:
- activeCount():Trả về số đối tượng thread mà là active.
- currentThread():Trả về số đối tượng thread trong Thread control của Caller.
- enumerate():Trả về một danh sách tất cả đối tượng thread mà hiện tại là active.
Bên cạnh đó, threading Module có lớp Thread để triển khai đa luồng. Lớp này có các phương thức sau:
- run():Là entry point cho một Thread.
- start():Bắt đầu một thread bởi gọi phương thức run().
- join([time]):Đợi cho các thread kết thúc.
- isAlive():Kiểm tra xem một thread có đang thực thi hay không.
- getName():Trả về tên của một thread.
- setName():Thiết lập tên của một thread.
Tạo Thread bởi sử dụng threading Module trong Python
Để triển khai một thread mới bởi sử dụng threading Module, bạn phải thực hiện:
- Định nghĩa một lớp con của lớp Thread.
- Ghi đè phương thức __init__(self [,args])để bổ sung thêm các tham số.
- Sau đó, ghi đè phương thức run(self [,args])để triển khai những gì thread cần thực hiện khi được bắt đầu.
Một khi bạn đã tạo lớp con Thread mới, bạn có thể tạo một instance của nó và sau đó bắt đầu một Thread bởi triệu hồi phương thức start().
Ví dụ
import threading
import timeexitFlag = 0class myThread (threading.Thread):
def __init__(self, threadID, name, counter):
threading.Thread.__init__(self)
self.threadID = threadID
self.name = name
self.counter = counter
def run(self):
print "Bat dau " + self.name
print_time(self.name, self.counter, 5)
print "Ket thuc " + self.namedef print_time(threadName, delay, counter):
while counter:
if exitFlag:
threadName.exit()
time.sleep(delay)
print "%s: %s" % (threadName, time.ctime(time.time()))
counter -= 1# Tao cac thread moi
thread1 = myThread(1, "Thread-1", 1)
thread2 = myThread(2, "Thread-2", 2)# Bat dau cac thread moi
thread1.start()
thread2.start()print "Ket thuc Main Thread"
Kết quả là:
Bat dau Thread-1
Bat dau Thread-2
Ket thuc Main Thread
Thread-1: Mon Nov 21 09:10:03 2015
Thread-1: Mon Nov 21 09:10:04 2015
Thread-2: Mon Nov 21 09:10:04 2015
Thread-1: Mon Nov 21 09:10:05 2015
Thread-1: Mon Nov 21 09:10:06 2015
Thread-2: Mon Nov 21 09:10:06 2015
Thread-1: Mon Nov 21 09:10:07 2015
Ket thuc Thread-1
Thread-2: Mon Nov 21 09:10:08 2015
Thread-2: Mon Nov 21 09:10:10 2015
Thread-2: Mon Nov 21 09:10:12 2015
Ket thuc Thread-2
Đồng bộ hóa các Thread trong Python
Python cung cấp threading Module, mà bao gồm một kỹ thuật locking cho phép bạn đồng bộ hóa các Thread một cách dễ dàng. Một lock mới được tạo bởi gọi phương thức Lock().
Phương thức acquire(blocking) của đối tượng lock mới này được sử dụng để ép các Thread chạy một cách đồng bộ. Tham số blocking tùy ý cho bạn khả năng điều khiển để xem một Thread có cần đợi để đạt được lock hay không.
Nếu tham số blocking được thiết lập là 0, tức là Thread ngay lập tức trả về một giá trị 0 nếu không thu được lock và trả về giá trị 1 nếu thu được lock. Nếu blocking được thiết lập là 1, thì Thread cần đợi cho đến khi lock được giải phóng.
Phương thức release() của đối tượng lock được sử dụng để giải phóng lock khi nó không cần nữa.
Ví dụ
import threading
import timeclass myThread (threading.Thread):
def __init__(self, threadID, name, counter):
threading.Thread.__init__(self)
self.threadID = threadID
self.name = name
self.counter = counter
def run(self):
print "Bat dau " + self.name
# Lay lock de dong bo hoa cac thread
threadLock.acquire()
print_time(self.name, self.counter, 3)
# Giai phong lock cho thread ke tiep
threadLock.release()def print_time(threadName, delay, counter):
while counter:
time.sleep(delay)
print "%s: %s" % (threadName, time.ctime(time.time()))
counter -= 1threadLock = threading.Lock()
threads = []# Tao cac thread moi
thread1 = myThread(1, "Thread-1", 1)
thread2 = myThread(2, "Thread-2", 2)# Bat dau cac thread moi
thread1.start()
thread2.start()# Them cac thread vao list
threads.append(thread1)
threads.append(thread2)# Doi cho tat ca thread ket thuc
for t in threads:
t.join()
print "Ket thuc Main Thread"
Kết quả là:
Bat dau Thread-1
Bat dau Thread-2
Thread-1: Mon Nov 21 09:11:28 2015
Thread-1: Mon Nov 21 09:11:29 2015
Thread-1: Mon Nov 21 09:11:30 2015
Thread-2: Mon Nov 21 09:11:32 2015
Thread-2: Mon Nov 21 09:11:34 2015
Thread-2: Mon Nov 21 09:11:36 2015
Ket thuc Main Thread
Queue Module: quyền ưu tiên đa luồng trong Python
Queue Module cho phép bạn tạo một đối tượng queue mới mà có thể giữ một số lượng item nào đó. Dưới đây là các phương thức:
- get():Xóa và trả về một item từ queue.
- put():Thêm một item tới một queue.
- qsize() :Trả về số item mà hiện tại đang trong queue.
- empty():Trả về true nếu queue là trống, nếu không thì trả về false.
- full():Trả về true nếu queue là đầy, nếu không thì trả về false.
Ví dụ
import Queue
import threading
import timeexitFlag = 0class myThread (threading.Thread):
def __init__(self, threadID, name, q):
threading.Thread.__init__(self)
self.threadID = threadID
self.name = name
self.q = q
def run(self):
print "Bat dau " + self.name
process_data(self.name, self.q)
print "Ket thuc " + self.namedef process_data(threadName, q):
while not exitFlag:
queueLock.acquire()
if not workQueue.empty():
data = q.get()
queueLock.release()
print "%s dang xu ly %s" % (threadName, data)
else:
queueLock.release()
time.sleep(1)threadList = ["Thread-1", "Thread-2", "Thread-3"]
nameList = ["One", "Two", "Three", "Four", "Five"]
queueLock = threading.Lock()
workQueue = Queue.Queue(10)
threads = []
threadID = 1# Tao cac thread moi
for tName in threadList:
thread = myThread(threadID, tName, workQueue)
thread.start()
threads.append(thread)
threadID += 1# Dien vao queue
queueLock.acquire()
for word in nameList:
workQueue.put(word)
queueLock.release()# Doi den khi queue la trong
while not workQueue.empty():
pass# Thong bao cho thread do la thoi gian de ket thuc
exitFlag = 1# Doi cho tat ca thread ket thuc
for t in threads:
t.join()
print "Ket thuc Main Thread"
Kết quả là:
Bat dau Thread-1
Bat dau Thread-2
Bat dau Thread-3
Thread-1 dang xu ly One
Thread-2 dang xu ly Two
Thread-3 dang xu ly Three
Thread-1 dang xu ly Four
Thread-2 dang xu ly Five
Ket thuc Thread-3
Ket thuc Thread-1
Ket thuc Thread-2
Ket thuc Main Thread
Xử lý XML trong Python
Thư viện Python chuẩn cung cấp các Interface hữu ích để làm việc với XML. Hai APIs cơ bản và được sử dụng nhiều nhât là SAX và DOM. SAX (viết tắt của Simple API for XML) là read-only trong khi DOM (viết tắt của Document Object Model) cho phép tạo các thay đổi tới XML file.
Chương này sẽ giới thiệu về cả hai Interface này, nhưng trước hết, chúng ta tạo một XML file đơn giản có tên là movies.xml để làm input:
Phân tích cú pháp XML với SAX APIs
Nói chung, bạn cần tạo riêng cho mình một ContentHandler là lớp con của xml.sax.ContentHandler.
ContentHandler của bạn sẽ xử lý các tag cụ thể và các thuộc tính của XML. Một đối tượng ContentHandler cung cấp các phương thức để xử lý các sự kiện parsing khác nhau.
Phương thức startDocument và endDocument được gọi tại phần bắt đầu và phần cuối của XML file. Phương thức characters(text) để truyền dữ liệu ký tự của XML thông qua tham số text.
Đối tượng ContentHandler được gọi tại phần bắt đầu và phần cuối của mỗi phần tử. Nếu Parser không trong namespace mode, thì các phương thức startElement(tag, thuoc_tinh) và endElement(tag) được gọi; nếu không thì, các phương thức tương ứng startElementNS và endElementNS được gọi. Ở đây, tham số tag là thẻ và thuoc_tinh là một đối tượng Attributes.
Bạn tìm hiểu một số phương thức quan trọng sau để hiểu rõ tiến trình xử lý hơn:
Phương thức make_parser trong Python
Phương thức sau tạo một đối tượng parser mới và trả về nó. Đối tượng parser đã được tạo này sẽ là kiểu parser đầu tiên mà hệ thống tìm thấy.
xml.sax.make_parser( [parser_list] )
Tham số parser_list là tùy ý, bao gồm một danh sách các parser để sử dụng, tất cả phải triển khai phương thức make_parser.
Phương thức parse trong Python
Phương thức này tạo một SAX parser và sử dụng nó để phân tích cú pháp một tài liệu.
xml.sax.parse( xmlfile, contenthandler[, errorhandler])
Chi tiết tham số:
- xmlfile: Đây là tên của XML file để đọc từ đó.
- contenthandler: Đây phải là một đối tượng ContentHandler.
- errorhandler:Nếu được xác định, thì nó phải là một đối tượng SAX ErrorHandler.
Phương thức parseString trong Python
Phương thức này cũng dùng để tạo một SAX parser và để phân tích cú pháp XML string đã cho.
xml.sax.parseString(xmlstring, contenthandler[, errorhandler])
Chi tiết về tham số:
- xmlstring: Là tên của XML string để đọc từ đó.
- contenthandler: Phải là một đối tượng ContentHandler.
- errorhandler:Nếu được xác định, thì nó phải là một đối tượng SAX ErrorHandler.
Ví dụ
import xml.sax
class Phim BoHandler( xml.sax.ContentHandler ):
def __init__(self):
self.CurrentData = ""
self.type = ""
self.format = ""
self.year = ""
self.rating = ""
self.stars = ""
self.description = ""
# Goi khi mot phan tu bat dau
def startElement(self, tag, attributes):
self.CurrentData = tag
if tag == "movie":
print "*****Phim Bo*****"
title = attributes["title"]
print "Ten Phim:", title
# Goi khi mot phan tu ket thuc
def endElement(self, tag):
if self.CurrentData == "type":
print "The loai:", self.type
elif self.CurrentData == "format":
print "Dinh dang:", self.format
elif self.CurrentData == "year":
print "Nam:", self.year
elif self.CurrentData == "rating":
print "Rating:", self.rating
elif self.CurrentData == "stars":
print "Dien vien:", self.stars
elif self.CurrentData == "description":
print "Gioi thieu:", self.description
self.CurrentData = ""
# Goi khi mot ky tu duoc doc
def characters(self, content):
if self.CurrentData == "type":
self.type = content
elif self.CurrentData == "format":
self.format = content
elif self.CurrentData == "year":
self.year = content
elif self.CurrentData == "rating":
self.rating = content
elif self.CurrentData == "stars":
self.stars = content
elif self.CurrentData == "description":
self.description = content
if ( __name__ == "__main__"):
# Tao mot XMLReader
parser = xml.sax.make_parser()
# Tat cac namepsace
parser.setFeature(xml.sax.handler.feature_namespaces, 0)
# ghi de ContextHandler mac dinh
Handler = Phim BoHandler()
parser.setContentHandler( Handler )
parser.parse("movies.xml")
Phân tích cú pháp XML với DOM APIs
DOM thực sự hữu ích với các ứng dụng truy cập ngẫu nhiên. SAX chỉ cho phép bạn xem một bit của tài liệu tại một thời điểm và không có quyền truy cập khác.
Dưới đây là cách nhanh nhất để tải một XML document và để tạo một đối tượng minidom bởi sử dụng xml.dom Module. Đối tượng minidom cung cấp một phương thức parser đơn giản mà tạo một DOM tree một cách nhanh chóng từ XML file.
Hàm parse(file [,parser]) của đối tượng minidom để phân tích cú pháp XML file đã được chỉ rõ bởi file bên trong một đối tượng DOM tree.
from xml.dom.minidom import parse
import xml.dom.minidom
# Mo mot tai lieu XML document boi su dung minidom parser
DOMTree = xml.dom.minidom.parse("movies.xml")
collection = DOMTree.documentElement
if collection.hasAttribute("shelf"):
print "Root element : %s" % collection.getAttribute("shelf")
# Lay tat ca phim trong bo suu tap
movies = collection.getElementsByTagName("movie")
# in chi tiet ve moi phim.
for movie in movies:
print "*****Phim Bo*****"
if movie.hasAttribute("title"):
print "Ten Phim: %s" % movie.getAttribute("title")
type = movie.getElementsByTagName('type')[0]
print "The loai: %s" % type.childNodes[0].data
format = movie.getElementsByTagName('format')[0]
print "Dinh dang: %s" % format.childNodes[0].data
rating = movie.getElementsByTagName('rating')[0]
print "Rating: %s" % rating.childNodes[0].data
description = movie.getElementsByTagName('description')[0]
print "Gioi thieu: %s" % description.childNodes[0].data