Tất cả các thể hiện bên trong Python đều phải là các instances (thể hiện) của một class nào đó, mà kế thừa từ class BaseException. Hai exception classes (lớp ngoại lệ) mà không liên quan tới nhau thông qua việc subclassing (kế thừa), thì sẽ không bao giờ tương đương với nhau, ngay cả khi chúng có cùng tên. Các built-in exceptions (các ngoại lệ được tích hợp sẵn trong Python) có thể được tạo ra bởi trình thông dịch hoặc bởi các built-in functions (các hàm được tích hợp sẵn trong Python).
Có một vài built-in exceptions trong Python sẽ được đưa ra khi có lỗi xảy ra. Các built-in exceptions này có thể được nhìn thấy bằng cách sử dụng built-in function là hàm local() như sau:
>>> locals()['__builtins__']
Câu lệnh này sẽ trả về một dictionary gồm các built-in exceptioms (các ngoại lệ được tích hợp sẵn), function – các hàm và các thuộc tính.
Nội dung chính
1. Base clsses – Các lớp cơ sở
Các exceptions (ngoại lệ) sau đây sẽ được sử dụng chủ yếu làm base classes (lớp cha/lớp cơ sở) cho các exceptions khác.
1.1. exception BaseException
Đây là base class (lớp cha) dành cho tất cả các built-in exceptions, tuy nhiên điều này không đồng nghĩa với việc các lớp ngoại lệ do người tự định nghĩa sẽ kế thừa trực tiếp từ cas BaseException. Đối với các user-defined classes (các lớp ngoại lệ do người dùng tự định nghĩa), class Exception sẽ được sử dụng. class BaseException sẽ chịu trách nhiệm tạo ra một chuỗi đại diện cho cái exception (ngoại lệ) bằng cách sử dụng hàm str() với các đối số được truyền vào. Một empty string – chuỗi rỗng sẽ được trả về nếu không có đối số nào được truyền vào.
– args: args chính là một tuple chứa các đối số, được cung cấp cho hàm constructor của class exception.
– with_traceback(tb): Phương thức này thường được sử dụng trong xử lý ngoại lệ. Phương thức này sẽ đặt tb thành một cái traceback mới dành cho exception này, và trả về exception object (đối tượng ngoại lệ).
– Giải thích thêm: Module traceback sẽ làm việc với call stack (ngăn xếp chứa các lời gọi hàm) để tạo ra các error messages – các thông báo lỗi. Một cái traceback chính là một bản báo cáo chứa thông tin về các lời gọi hàm được thực hiện trong code của bạn, tại một thời điểm cụ thể. Các tracebacks được biết tới với nhiều cái tên, chẳng hạn như stack trace, stack traceback, backtrace, v.v… Trong Python, thuật ngữ được sử dụng là traceback. Khi chương trình của bạn gặp phải lỗi, làm kích hoạt ngoại lệ, Python sẽ in ra traceback hiện tại để giúp bạn có thể điều tra thêm về nguyên nhân gây lỗi.
– Ví dụ:
try:
...
except SomeException:
tb = sys.exc_info()[2]
raise OtherException(...).with_traceback(tb)
1.2. exception Exception
Đây là base class dành cho tất cả các built-in non-system-exiting exceptions (ngoại lệ được tích hợp sẵn, không gây thoát khỏi hệ thống). Tất cả các user-defined exceptions (ngoại lệ do người dùng tự tạo ra) đều nên được kế thừa/dẫn xuất từ class này.
1.3. exception ArithmeticError
Đây là baseclass của những built-in exceptions (ngoại lệ được tích hợp sẵn) được kích hoạt khi xảy ra các lỗi số học khác nhau, chẳng hạn như:
– OverflowError
– ZeroDivisionError
– FloatingPointError
– Ví dụ:
# -----------------------------------------------------------
#Cafedev.vn - Kênh thông tin IT hàng đầu Việt Nam
#@author cafedevn
#Contact: cafedevn@gmail.com
#Fanpage: https://www.facebook.com/cafedevn
#Group: https://www.facebook.com/groups/cafedev.vn/
#Instagram: https://instagram.com/cafedevn
#Twitter: https://twitter.com/CafedeVn
#Linkedin: https://www.linkedin.com/in/cafe-dev-407054199/
#Pinterest: https://www.pinterest.com/cafedevvn/
#YouTube: https://www.youtube.com/channel/UCE7zpY_SlHGEgo67pHxqIoA/
# -----------------------------------------------------------
try:
a = 10/0
print a
except ArithmeticError:
print "This statement is raising an arithmetic exception."
else:
print "Success."
– Kết quả in ra là:
This statement is raising an arithmetic exception.
1.4. exception BufferError
Cái exception (ngoại lệ) này sẽ được kích hoạt khi chương trình không thể thực hiện được các hoạt động liên quan đến buffer (bộ nhớ đệm).
1.5. exception LookupError
Đây là base class (lớp cha) của những exceptions mà được kích hoạt khi một key (từ khóa) hoặc một index (vị trí phần tử mảng) được sử dụng trên một kiểu dữ liệu tham chiếu hay kiểu dữ liệu chuỗi là không hợp lệ, hoặc không thể tìm thấy. Các exceptions (ngoại lệ) sẽ được kích hoạt là:
– KeyError
– IndexError
Ví dụ:
try:
a = [1, 2, 3]
print a[3]
except LookupError:
print "Index out of bound error."
else:
print "Success"
Kết quả in ra là:
Index out of bound error.
2. Concrete exceptions – Các ngoại lệ cụ thể
Dưới đây là các exceptions (ngoại lệ) thường xuyên được kích hoạt.
2.1. exception AssertionError
Một cái exception AssertionError sẽ được kích hoạt khi có một câu lệnh assert bị thất bại.
Ví dụ:
assert False, 'The assertion failed'
Kết quả in ra là:
Traceback (most recent call last):
File "exceptions_AssertionError.py", line 12, in
assert False, 'The assertion failed'
AssertionError: The assertion failed
2.2. exception AttributeError
Một AttributeError sẽ được kích hoạt khi một phép tham chiếu tới thuộc tính hoặc một phép gán cho thuộc tính bị thất bại, chẳng hạn như khi một thuộc tính không tồn tại lại được tham chiếu tới.
Ví dụ:
class Attributes(object):
pass
object = Attributes()
print object.attribute
Kết quả in ra là:
Traceback (most recent call last):
File "d912bae549a2b42953bc62da114ae7a7.py", line 5, in
print object.attribute
AttributeError: 'Attributes' object has no attribute 'attribute'
2.3. exception EOFError
Một ngoại lệ EOFError sẽ được đưa ra khi các hàm được tích hợp sẵn trong Python chẳng hạn như hàm input() gặp phải một cái end-of-file condition (EOF), tức là một điều kiện kết thúc tệp tin, trong khi nó không đọc bất kỳ dữ liệu nào. Các phương thức làm việc với file như readline() sẽ trả về một chuỗi rỗng (empty string) khi chúng gặp phải EOF.
Ví dụ:
while True:
data = raw_input('Enter name : ')
print 'Hello ', data
Kết quả in ra là:
Enter Name :Hello Aditi
Enter Name :Traceback (most recent call last):
File "exceptions_EOFError.py", line 13, in
data = raw_input('Enter name :')
EOFError: EOF when reading a line
2.4. exception FloatingPointError
Một ngoại lệ FloatingPointError sẽ được đưa ra khi có một phép toán với số dấu phẩy động (floating point) bị thất bại. Ngoại lệ này sẽ luôn luôn được khai báo, nhưng chỉ có thể được đưa ra khi Python được cấu hình với tùy chọn the-with-fpectl, hoặc cái symol WANT_SIGFPE_HANDLER được khai báo bên trong file pyconfig.h.
Ví dụ:
import math
print math.exp(1000)
Kết quả in ra là:
Traceback (most recent call last):
File "", line 1, in
FloatingPointError: in math_1
2.5. exception GeneratorExit
Ngoại lệ này kế thừa trực tiếp từ class BaseException thay vì class Exception, bởi vì về mặt kỹ thuật nó không phải là một error (lỗi). Một ngoại lệ GeneratorExit sẽ được đưa ra khi có một generator hoặc một coroutine bị đóng lại.
- Ví dụ:
# -----------------------------------------------------------
#Cafedev.vn - Kênh thông tin IT hàng đầu Việt Nam
#@author cafedevn
#Contact: cafedevn@gmail.com
#Fanpage: https://www.facebook.com/cafedevn
#Group: https://www.facebook.com/groups/cafedev.vn/
#Instagram: https://instagram.com/cafedevn
#Twitter: https://twitter.com/CafedeVn
#Linkedin: https://www.linkedin.com/in/cafe-dev-407054199/
#Pinterest: https://www.pinterest.com/cafedevvn/
#YouTube: https://www.youtube.com/channel/UCE7zpY_SlHGEgo67pHxqIoA/
# -----------------------------------------------------------
def my_generator():
try:
for i in range(5):
print 'Yielding', i
yield i
except GeneratorExit:
print 'Exiting early'
g = my_generator()
print g.next()
g.close()
- Kết quả in ra là:
Yielding 0
0
Exiting early
2.6. exception ImportError
Một ngoại lệ ImportError sẽ được đưa ra khi câu lệnh import không thể tải được một module nào đó hoặc khi đoạn “from list” trong câu lệnh from … import có chứa một tên module mà không thể tìm thấy được.
- Ví dụ 1:
import module_does_not_exist
- Kết quả in ra là:
Traceback (most recent call last):
File "exceptions_ImportError_nomodule.py", line 12, in
import module_does_not_exist
ImportError: No module named module_does_not_exist
- Ví dụ 2:
from exceptions import Userexception
- Kết quả in ra là:
Traceback (most recent call last):
File "exceptions_ImportError_missingname.py", line 12, in
from exceptions import Userexception
ImportError: cannot import name Userexception
2.7. exception ModuleNotFoundError
Đây là subclass (lớp con) của class ImportError, cái mà được kích hoạt khi câu lệnh import không thể tìm thấy được module cần tải. Nó cũng được đưa ra khi None được tìm thấy bên trong sys.modules.
2.8. exception IndexError
Một ngoại lệ IndexError sẽ được đưa ra khi xuất hiện một truy vấn đến phần tử của một kiểu dữ liệu nối tiếp (ví dụ như mảng), mà phần tử đó nằm ngoài giới hạn vị trí cho phép.
- Ví dụ:
array = [ 0, 1, 2 ]
print array[3]
- Kết quả in ra là:
Traceback (most recent call last):
File "exceptions_IndexError.py", line 13, in
print array[3]
IndexError: list index out of range
2.9. exception KeyError
Một ngoại lệ KeyError sẽ được đưa ra khi có một từ khóa tham chiếu mà không thể tìm thấy được bên trong tập hợp các từ khóa hiện tại.
- Ví dụ:
array = { 'a':1, 'b':2 }
print array['c']
- Kết quả in ra là:
Traceback (most recent call last):
File "exceptions_KeyError.py", line 13, in
print array['c']
KeyError: 'c'
2.10. exception KeyboardInterrupt
Ngoại lệ này sẽ được kích hoạt khi người dùng nhấn vào các phím/tổ hợp phím có chức năng ngắt như Control-C hoặc Delete.
- Ví dụ:
# -----------------------------------------------------------
#Cafedev.vn - Kênh thông tin IT hàng đầu Việt Nam
#@author cafedevn
#Contact: cafedevn@gmail.com
#Fanpage: https://www.facebook.com/cafedevn
#Group: https://www.facebook.com/groups/cafedev.vn/
#Instagram: https://instagram.com/cafedevn
#Twitter: https://twitter.com/CafedeVn
#Linkedin: https://www.linkedin.com/in/cafe-dev-407054199/
#Pinterest: https://www.pinterest.com/cafedevvn/
#YouTube: https://www.youtube.com/channel/UCE7zpY_SlHGEgo67pHxqIoA/
# -----------------------------------------------------------
try:
print 'Press Return or Ctrl-C:',
ignored = raw_input()
except Exception, err:
print 'Caught exception:', err
except KeyboardInterrupt, err:
print 'Caught KeyboardInterrupt'
else:
print 'No exception'
- Kết quả in ra là:
Press Return or Ctrl-C: ^CCaught KeyboardInterrupt
2.11. exception MemoryError
Ngoại lệ MemoryError sẽ được đưa ra khi có một tác vụ gây tiêu hao quá nhiều bộ nhớ
- Ví dụ:
def fact(a):
factors = []
for i in range(1, a+1):
if a%i == 0:
factors.append(i)
return factors
num = 600851475143
print fact(num)
- Kết quả in ra là:
Traceback (most recent call last):
File "4af5c316c749aff128df20714536b8f3.py", line 9, in
print fact(num)
File "4af5c316c749aff128df20714536b8f3.py", line 3, in fact
for i in range(1, a+1):
MemoryError
2.12. exception NameError
Ngoại lệ này được đưa ra khi có một tên biến cục bộ hoặc tên biến toàn cục mà không thể tìm thấy được. Ví dụ, một tên biến đặt sai cách.
- Ví dụ:
def func():
print ans
func()
- Kết quả in ra là:
Traceback (most recent call last):
File "cfba0a5196b05397e0a23b1b5b8c7e19.py", line 4, in
func()
File "cfba0a5196b05397e0a23b1b5b8c7e19.py", line 2, in func
print ans
NameError: global name 'ans' is not defined
2.13. exception NotImplementedError
Ngoại lệ này được kế thừa/dẫn xuất ra từ class ngoại lệ RuntimeError. Các abstract methods (phương thức trừu tượng) trong các class do người dùng tự định nghĩa, sẽ đưa ra ngoại lệ này khi các class kế thừa chúng/được dẫn xuất ra từ chúng thực hiện override (ghi đè) các phương thức đó.
- Ví dụ:
# -----------------------------------------------------------
#Cafedev.vn - Kênh thông tin IT hàng đầu Việt Nam
#@author cafedevn
#Contact: cafedevn@gmail.com
#Fanpage: https://www.facebook.com/cafedevn
#Group: https://www.facebook.com/groups/cafedev.vn/
#Instagram: https://instagram.com/cafedevn
#Twitter: https://twitter.com/CafedeVn
#Linkedin: https://www.linkedin.com/in/cafe-dev-407054199/
#Pinterest: https://www.pinterest.com/cafedevvn/
#YouTube: https://www.youtube.com/channel/UCE7zpY_SlHGEgo67pHxqIoA/
# -----------------------------------------------------------
class BaseClass(object):
"""Defines the interface"""
def __init__(self):
super(BaseClass, self).__init__()
def do_something(self):
"""The interface, not implemented"""
raise NotImplementedError(self.__class__.__name__ + '.do_something')
class SubClass(BaseClass):
"""Implementes the interface"""
def do_something(self):
"""really does something"""
print self.__class__.__name__ + ' doing something!'
SubClass().do_something()
BaseClass().do_something()
- Kết quả in ra là:
Traceback (most recent call last):
File "b32fc445850cbc23cd2f081ba1c1d60b.py", line 16, in
BaseClass().do_something()
File "b32fc445850cbc23cd2f081ba1c1d60b.py", line 7, in do_something
raise NotImplementedError(self.__class__.__name__ + '.do_something')
NotImplementedError: BaseClass.do_something
2.14. exception OSError([arg])
Ngoại lệ OSError sẽ được kích hoạt khi có một hàm hệ thống trả về một lỗi liên quan đến hệ thống (system-related error), bao gồm các lỗi về I/O (nhập/xuất) chẳng hạn như lỗi “file not found” hoặc lỗi “disk full”.
- Ví dụ:
def func():
print ans
func()
- Kết quả in ra là:
Traceback (most recent call last):
File "442eccd7535a2704adbe372cb731fc0f.py", line 4, in
print i, os.ttyname(i)
OSError: [Errno 25] Inappropriate ioctl for device
2.15. exception OverflowError
Ngoại lệ OverflowError sẽ được đưa ra khi kết quả của một phép toán số học vượt ra ngoài giới hạn giá trị cho phép. Các số nguyên sẽ đưa ra ngoại lệ MemoryError thay vì ngoại vệ OverflowError. Ngoại lệ OverflowError đôi khi được đưa ra cho các số nguyên mà nằm ngoài giới hạn giá trị cho phép. Các phép toán với số dấu phẩy động (floating point number) sẽ không được kiểm tra, bởi vì ngôn ngữ C không chuẩn hóa việc xử lý ngoại lệ dành cho số dấu phẩy động (floating point number).
- Ví dụ:
# -----------------------------------------------------------
#Cafedev.vn - Kênh thông tin IT hàng đầu Việt Nam
#@author cafedevn
#Contact: cafedevn@gmail.com
#Fanpage: https://www.facebook.com/cafedevn
#Group: https://www.facebook.com/groups/cafedev.vn/
#Instagram: https://instagram.com/cafedevn
#Twitter: https://twitter.com/CafedeVn
#Linkedin: https://www.linkedin.com/in/cafe-dev-407054199/
#Pinterest: https://www.pinterest.com/cafedevvn/
#YouTube: https://www.youtube.com/channel/UCE7zpY_SlHGEgo67pHxqIoA/
# -----------------------------------------------------------
import sys
print 'Regular integer: (maxint=%s)' % sys.maxint
try:
i = sys.maxint * 3
print 'No overflow for ', type(i), 'i =', i
except OverflowError, err:
print 'Overflowed at ', i, err
print
print 'Long integer:'
for i in range(0, 100, 10):
print '%2d' % i, 2L ** i
print
print 'Floating point values:'
try:
f = 2.0**i
for i in range(100):
print i, f
f = f ** 2
except OverflowError, err:
print 'Overflowed after ', f, err
- Kết quả in ra là:
Regular integer: (maxint=9223372036854775807)
No overflow for i = 27670116110564327421
Long integer:
0 1
10 1024
20 1048576
30 1073741824
40 1099511627776
50 1125899906842624
60 1152921504606846976
70 1180591620717411303424
80 1208925819614629174706176
90 1237940039285380274899124224
Floating point values:
0 1.23794003929e+27
1 1.53249554087e+54
2 2.34854258277e+108
3 5.5156522631e+216
Overflowed after 5.5156522631e+216 (34, 'Numerical result out of range')
2.16. exception RecursionError
Ngoại lệ RecursionError được kế thừa/dẫn xuất từ class RuntimeError. Ngoại lệ này được đưa ra khi trình thông dịch (interpreter) phát hiện ra độ sâu đệ quy tối đa đã bị vượt quá.
2.17. exception ReferenceError
Ngoại lệ ReferenceError được đưa ra khi một proxy tham chiếu yếu (weak reference) được sử dụng để truy cập tới một thuộc tính của tham chiếu, sau khi tham chiếu này đã bị thu dọn bởi garbage collector.
- Ví dụ:
import gc
import weakref
class Foo(object):
def __init__(self, name):
self.name = name
def __del__(self):
print '(Deleting %s)' % self
obj = Foo('obj')
p = weakref.proxy(obj)
print 'BEFORE:', p.name
obj = None
print 'AFTER:', p.name
- Kết quả in ra là:
BEFORE: obj
(Deleting )
AFTER:
Traceback (most recent call last):
File "49d0c29d8fe607b862c02f4e1cb6c756.py", line 17, in
print 'AFTER:', p.name
ReferenceError: weakly-referenced object no longer exists
2.18. exception RuntimeError
Ngoại lệ RuntimeError được đưa ra khi không có ngoại lệ phù hợp nào khác được áp dụng. Nó trả về một chuỗi cho biết chính xác những phần code nào đã sai.
2.19. exception StopIteration
Ngoại lệ StopIteration được đưa ra bởi hàm được tích hợp sẵn next() và phương thức __next__() của iterator để báo hiệu rằng tất cả các items đều được tạo ra bởi iterator.
- Ví dụ:
Arr = [3, 1, 2]
i=iter(Arr)
print i
print i.next()
print i.next()
print i.next()
print i.next()
- Kết quả in ra là:
3
1
2
Traceback (most recent call last):
File "2136fa9a620e14f8436bb60d5395cc5b.py", line 8, in
print i.next()
StopIteration
2.20. exception SyntaxError
Ngoại lệ SyntaxError được đưa ra khi parser (trình phân tích cú pháp chương trình) gặp được một lỗi cú pháp. Một lỗi cú pháp có thể xảy ra bên trong một câu lệnh import hoặc trong khi gọi các hàm được tích hợp sẵn trong Python như exec() hoặc eval(), hoặc khi đọc vào phần initial script (đoạn mã kịch bản để khởi tạo), hoặc khi đọc dữ liệu vào từ standard input.
- Ví dụ:
try:
print eval('cafedev')
except SyntaxError, err:
print 'Syntax error %s (%s-%s): %s' % \
(err.filename, err.lineno, err.offset, err.text)
print err
- Kết quả in ra là:
Syntax error (1-9): cafedev
invalid syntax (, line 1)
2.21. exception SystemError
Ngoại lệ SystemError được đưa ra khi trình thông dịch (interpreter) tìm thấy một internal error – tức là một lỗi nội bộ, lỗi ở bên trong. Giá trị được liên kết với ngoại lệ này là một chuỗi chỉ ra điều gì đã sai.
2.22. exception SystemExit
Ngoại lệ SystemExit được đưa ra khi hàm sys.exit() được gọi. Một lời gọi tới hàm sys.exit() sẽ được dịch thành một ngoại lệ để thực thi các clean-up handlers, tức là các trình xử lý việc dọn dẹp (thường được đặt bên trọng mệnh đề finally của các câu lệnh try), và để debug (gỡ lỗi) một phần mã script mà không gây ra nguy cơ mất kiểm soát nào.
2.23. exception TypeError
Ngoại lệ TypeError được đưa ra khi một phép toán hoặc một hàm được áp dụng cho một đối tượng có kiểu dữ liệu không phù hợp. Ngoại lệ này sẽ trả về một chuỗi cung cấp thông tin chi tiết về việc kiểu dữ liệu không khớp.
- Ví dụ:
arr = ('tuple', ) + 'string'
print arr
- Kết quả in ra là:
Traceback (most recent call last):
File "30238c120c0868eba7e13a06c0b1b1e4.py", line 1, in
arr = ('tuple', ) + 'string'
TypeError: can only concatenate tuple (not "str") to tuple
2.24. exception UnboundLocalError
Ngoại lệ UnboundLocalError là một subclass (lớp con) của class NameError được đưa ra khi một tham chiếu được tạo ra để trỏ đến một biến cục bộ (local variable) bên trong một hàm hoặc phương thức, nhưng không có giá trị nào được gán cho biến đó.
- Ví dụ:
def global_name_error():
print unknown_global_name
def unbound_local():
local_val = local_val + 1
print local_val
try:
global_name_error()
except NameError, err:
print 'Global name error:', err
try:
unbound_local()
except UnboundLocalError, err:
print 'Local name error:', err
- Kết quả in ra là:
Global name error: global name 'unknown_global_name' is not defined
Local name error: local variable 'local_val' referenced before assignment
2.25. exception UnicodeError
Ngoại lệ này là một subclass (lớp con) của class ValueError. Ngoại lệ UnicodeError được đưa ra khi có lỗi liên quan đến việc endcoding và decoding các ký tự Unicode xảy ra.
2.26. exception ValueError
Một ngoại lệ ValueError được đưa ra khi có một hàm hoặc một phép toán được tích hợp sẵn trong Python nhận được một đối số mà có kiểu dữ liệu đúng, nhưng lại chứa giá trị không hợp lệ.
- Ví dụ:
print int('a')
- Kết quả in ra là:
Traceback (most recent call last):
File "44f00efda935715a3c5468d899080381.py", line 1, in
print int('a')
ValueError: invalid literal for int() with base 10: 'a'
2.27. exception ZeroDivisionError
Một ngoại lệ ZeroDivisionError được đưa ra khi đối số thwus hai của một phép chia hoặc một phép modulo là 0. Ngoại lệ này sẽ trả về một chuỗi chỉ ra kiểu dữ liệu của các toán hạng và phép toán.
- Ví dụ:
print 1/0
- Kết quả in ra là:
Traceback (most recent call last):
File "c31d9626b41e53d170a78eac7d98cb85.py", line 1, in
print 1/0
ZeroDivisionError: integer division or modulo by zero
Nguồn và Tài liệu tiếng anh tham khảo:
Tài liệu từ cafedev:
- Full series tự học Python từ cơ bản tới nâng cao tại đây nha.
- Ebook về python tại đây.
- Các series tự học lập trình khác
Nếu bạn thấy hay và hữu ích, bạn có thể tham gia các kênh sau của cafedev để nhận được nhiều hơn nữa:
Chào thân ái và quyết thắng!