Python - Exceptions Handling

Exception Handling in Python

Xử lý ngoại lệ trong Python đề cập đến việc quản lý các lỗi thời gian chạy có thể xảy ra trong quá trình thực thi chương trình. Trong Python, các ngoại lệ được phát sinh khi có lỗi hoặc tình huống không mong muốn xảy ra trong quá trình thực thi chương trình, chẳng hạn như chia cho số không, cố gắng truy cập vào một tệp không tồn tại, hoặc cố gắng thực hiện một phép toán trên các kiểu dữ liệu không tương thích.

Python cung cấp hai tính năng rất quan trọng để xử lý bất kỳ lỗi không mong đợi nào trong các chương trình Python của bạn và để thêm khả năng gỡ lỗi vào chúng −

  • Exception Handling − Điều này sẽ được đề cập trong hướng dẫn này. Dưới đây là danh sách các Exception tiêu chuẩn có sẵn trong Python: Standard Exceptions .

  • Assertions − Điều này sẽ được đề cập trong hướng dẫn Assertions in Python .

Assertions in Python

Một câu lệnh khẳng định (assertion) là một kiểm tra hợp lý mà bạn có thể bật hoặc tắt khi bạn đã hoàn tất việc kiểm tra chương trình.

Cách dễ nhất để nghĩ về một câu lệnh khẳng định là so sánh nó với một câu lệnh raise-if (hoặc chính xác hơn là một câu lệnh raise-if-not). Một biểu thức được kiểm tra, và nếu kết quả trả về là sai, một ngoại lệ sẽ được kích hoạt.

Assertions are carried out by the assert statement, the newest keyword to Python, introduced in version 1.5.

Các lập trình viên thường đặt các khẳng định (assertions) ở đầu một hàm để kiểm tra đầu vào hợp lệ, và sau một cuộc gọi hàm để kiểm tra đầu ra hợp lệ.

The assert Statement

Khi gặp một câu lệnh assert, Python sẽ đánh giá biểu thức đi kèm, mà hy vọng là đúng. Nếu biểu thức đó sai, Python sẽ phát sinh một ngoại lệ AssertionError .

Giá trị syntax cho assert là −

assert Expression[, Arguments]

Nếu điều kiện xác nhận không thành công, Python sẽ sử dụng ArgumentExpression làm đối số cho AssertionError. Các ngoại lệ AssertionError có thể được bắt và xử lý như bất kỳ ngoại lệ nào khác bằng cách sử dụng câu lệnh try-except, nhưng nếu không được xử lý, chúng sẽ kết thúc chương trình và tạo ra một trace back.

Example

Dưới đây là một hàm chuyển đổi nhiệt độ từ độ Kelvin sang độ Fahrenheit. Vì không có nhiệt độ nào thấp hơn không độ Kelvin, hàm sẽ dừng lại nếu thấy nhiệt độ âm.

def KelvinToFahrenheit(Temperature):
   assert (Temperature >= 0),"Colder than absolute zero!"
   return ((Temperature-273)*1.8)+32
print (KelvinToFahrenheit(273))
print (int(KelvinToFahrenheit(505.78)))
print (KelvinToFahrenheit(-5))

Khi đoạn mã trên được thực thi, nó sẽ tạo ra kết quả sau −

32.0
451
Traceback (most recent call last):
File "test.py", line 9, in <module>
print (KelvinToFahrenheit(-5))
File "test.py", line 4, in KelvinToFahrenheit
assert (Temperature >= 0),"Colder than absolute zero!"
AssertionError: Colder than absolute zero!

What is Exception?

Một ngoại lệ là một sự kiện xảy ra trong quá trình thực thi của một chương trình, làm gián đoạn luồng thực hiện bình thường của các lệnh trong chương trình. Nói chung, khi một đoạn mã Python gặp phải một tình huống mà nó không thể xử lý, nó sẽ phát sinh một ngoại lệ. Một ngoại lệ là một đối tượng Python đại diện cho một lỗi.

Khi một script Python phát sinh ngoại lệ, nó phải xử lý ngoại lệ ngay lập tức, nếu không nó sẽ kết thúc và thoát.

Handling an Exception in Python

Nếu bạn có một số mã nghi ngờ có thể gây ra ngoại lệ, bạn có thể bảo vệ chương trình của mình bằng cách đặt mã nghi ngờ trong một khối try : . Sau khối try : , hãy bao gồm một câu lệnh except : , theo sau là một khối mã xử lý vấn đề một cách tinh tế nhất có thể.

  • Khối try chứa các câu lệnh có khả năng gây ra ngoại lệ.

  • Nếu xảy ra ngoại lệ, chương trình sẽ nhảy đến khối except .

  • Nếu không có ngoại lệ trong khối try : thì khối except : sẽ bị bỏ qua.

Syntax

Dưới đây là cú pháp đơn giản của các khối try...except...else

try:
   You do your operations here
   ......................
except ExceptionI:
   If there is ExceptionI, then execute this block.
except ExceptionII:
   If there is ExceptionII, then execute this block.
   ......................
else:
   If there is no exception then execute this block.

Dưới đây là một vài điểm quan trọng về cú pháp đã đề cập ở trên −

  • Một câu lệnh try duy nhất có thể có nhiều câu lệnh except. Điều này hữu ích khi khối try chứa các câu lệnh có thể ném ra các loại ngoại lệ khác nhau.

  • Bạn cũng có thể cung cấp một điều khoản tổng quát except , điều này sẽ xử lý bất kỳ ngoại lệ nào.

  • Sau các câu lệnh except, bạn có thể bao gồm một câu lệnh else . Mã trong khối else sẽ được thực thi nếu mã trong khối try: không phát sinh ngoại lệ.

  • Khối else là một nơi tốt để đặt mã không cần sự bảo vệ của khối try:.

Example

Ví dụ này mở một tệp, ghi nội dung vào tệp và thoát một cách suôn sẻ vì không có vấn đề gì xảy ra.

try:
   fh = open("testfile", "w")
   fh.write("This is my test file for exception handling!!")
except IOError:
   print ("Error: can\'t find file or read data")
else:
   print ("Written content in the file successfully")
   fh.close()

Nó sẽ tạo ra output

Written content in the file successfully

Tuy nhiên, hãy thay đổi tham số mode trong hàm open() thành "w". Nếu testfile chưa có sẵn, chương trình sẽ gặp IOError trong khối except và in ra thông báo lỗi sau:

Error: can't find file or read data

Example

Ví dụ này cố gắng mở một tệp mà bạn không có quyền ghi, vì vậy nó sẽ gây ra một ngoại lệ −

try:
   fh = open("testfile", "r")
   fh.write("This is my test file for exception handling!!")
except IOError:
   print ("Error: can\'t find file or read data")
else:
   print ("Written content in the file successfully")

Điều này tạo ra kết quả sau −

Error: can't find file or read data

The except Clause with No Exceptions

Bạn cũng có thể sử dụng câu lệnh except mà không định nghĩa bất kỳ ngoại lệ nào như sau −

try:
   You do your operations here;
   ......................
except:
   If there is any exception, then execute this block.
   ......................
else:
   If there is no exception then execute this block. 

Loại câu lệnh try-except này sẽ bắt tất cả các ngoại lệ xảy ra. Tuy nhiên, việc sử dụng loại câu lệnh try-except này không được coi là một thực hành lập trình tốt, vì nó bắt tất cả các ngoại lệ nhưng không yêu cầu lập trình viên xác định nguyên nhân gốc rễ của vấn đề có thể xảy ra.

The except Clause with Multiple Exceptions

Bạn cũng có thể sử dụng câu lệnh except giống như sau để xử lý nhiều ngoại lệ:

try:
   You do your operations here;
   ......................
except(Exception1[, Exception2[,...ExceptionN]]]):
   If there is any exception from the given exception list, 
   then execute this block.
   ......................
else:
   If there is no exception then execute this block. 

The try-finally Clause

Bạn có thể sử dụng một khối finally: cùng với một khối try: . Khối finally là nơi để đặt bất kỳ mã nào phải được thực thi, cho dù khối try có gây ra ngoại lệ hay không. Cú pháp của câu lệnh try-finally như sau −

try:
   You do your operations here;
   ......................
   Due to any exception, this may be skipped.
finally:
   This would always be executed.
   ......................

Bạn không thể sử dụng else cùng với một khối finally.

Example

try:
   fh = open("testfile", "w")
   fh.write("This is my test file for exception handling!!")
finally:
   print ("Error: can\'t find file or read data")

Nếu bạn không có quyền mở tệp ở chế độ ghi, thì điều này sẽ tạo ra kết quả sau −

Error: can't find file or read data

Ví dụ tương tự có thể được viết một cách rõ ràng hơn như sau −

try:
   fh = open("testfile", "w")
   try:
      fh.write("This is my test file for exception handling!!")
   finally:
      print ("Going to close the file")
      fh.close()
except IOError:
   print ("Error: can\'t find file or read data")

Khi một ngoại lệ được ném ra trong khối try , quá trình thực thi ngay lập tức chuyển sang khối finally . Sau khi tất cả các câu lệnh trong khối finally được thực thi, ngoại lệ sẽ được ném lại và được xử lý trong các câu lệnh except nếu có trong lớp cao hơn tiếp theo của câu lệnh try-except .

Argument of an Exception

Một ngoại lệ có thể có một tham số , là một giá trị cung cấp thông tin bổ sung về vấn đề. Nội dung của tham số thay đổi tùy theo ngoại lệ. Bạn có thể bắt tham số của một ngoại lệ bằng cách cung cấp một biến trong câu lệnh except như sau −

try:
   You do your operations here;
   ......................
except ExceptionType, Argument:
   You can print value of Argument here...

Nếu bạn viết mã để xử lý một ngoại lệ duy nhất, bạn có thể có một biến theo sau tên của ngoại lệ trong câu lệnh except. Nếu bạn đang bắt nhiều ngoại lệ, bạn có thể có một biến theo sau bộ ngoại lệ.

Biến này nhận giá trị của ngoại lệ chủ yếu chứa nguyên nhân của ngoại lệ. Biến có thể nhận một giá trị duy nhất hoặc nhiều giá trị dưới dạng một tuple. Tuple này thường chứa chuỗi lỗi, số lỗi và vị trí lỗi.

Example

Dưới đây là một ví dụ cho một ngoại lệ đơn lẻ −

# Define a function here.
def temp_convert(var):
   try:
      return int(var)
   except ValueError as Argument:
      print ("The argument does not contain numbers\n", Argument)

# Call above function here.
temp_convert("xyz")

Điều này tạo ra kết quả sau −

The argument does not contain numbers
invalid literal for int() with base 10: 'xyz'

Raising an Exceptions

Bạn có thể ném ngoại lệ theo nhiều cách khác nhau bằng cách sử dụng câu lệnh raise. Cú pháp chung cho câu lệnh raise như sau.

Syntax

raise [Exception [, args [, traceback]]]

Ở đây, Exception là loại ngoại lệ (ví dụ, NameError) và argument là một giá trị cho tham số ngoại lệ. Tham số này là tùy chọn; nếu không được cung cấp, tham số ngoại lệ sẽ là None.

Tham số cuối cùng, trace back, cũng là tùy chọn (và hiếm khi được sử dụng trong thực tế), và nếu có, nó là đối tượng traceback được sử dụng cho ngoại lệ.

Example

Một ngoại lệ có thể là một chuỗi, một lớp hoặc một đối tượng. Hầu hết các ngoại lệ mà lõi Python phát sinh là các lớp, với một đối số là một thể hiện của lớp đó. Việc định nghĩa các ngoại lệ mới khá dễ dàng và có thể được thực hiện như sau −

def functionName( level ):
   if level < 1:
      raise "Invalid level!", level
      # The code below to this would not be executed
      # if we raise the exception

Note: Để bắt một ngoại lệ, một câu lệnh "except" phải tham chiếu đến cùng một ngoại lệ được ném ra, có thể là đối tượng lớp hoặc chuỗi đơn giản. Ví dụ, để bắt ngoại lệ trên, chúng ta phải viết câu lệnh except như sau −

try:
   Business Logic here...
except "Invalid level!":
   Exception handling here...
else:
   Rest of the code here...

User-Defined Exceptions

Python cũng cho phép bạn tạo ra các ngoại lệ của riêng mình bằng cách kế thừa các lớp từ các ngoại lệ tích hợp sẵn tiêu chuẩn.

Dưới đây là một ví dụ liên quan đến RuntimeError . Ở đây, một lớp được tạo ra và kế thừa từ RuntimeError . Điều này hữu ích khi bạn cần hiển thị thông tin cụ thể hơn khi một ngoại lệ bị bắt.

Trong khối try, ngoại lệ do người dùng định nghĩa được ném ra và bị bắt trong khối except. Biến e được sử dụng để tạo một thể hiện của lớp Networkerror .

class Networkerror(RuntimeError):
   def __init__(self, arg):
      self.args = arg

Vì vậy, một khi bạn đã định nghĩa lớp ở trên, bạn có thể ném ngoại lệ như sau −

try:
   raise Networkerror("Bad hostname")
except Networkerror,e:
   print (e.args)

Standard Exceptions

Dưới đây là danh sách các Ngoại lệ Chuẩn có sẵn trong Python −

Sr.No. Exception Name & Description
1 Exception Base class for all exceptions
2 StopIteration Raised when the next() method of an iterator does not point to any object.
3 SystemExit Raised by the sys.exit() function.
4 StandardError Base class for all built-in exceptions except StopIteration and SystemExit.
5 ArithmeticError Base class for all errors that occur for numeric calculation.
6 OverflowError Raised when a calculation exceeds maximum limit for a numeric type.
7 FloatingPointError Raised when a floating point calculation fails.
8 ZeroDivisionError Raised when division or modulo by zero takes place for all numeric types.
9 AssertionError Raised in case of failure of the Assert statement.
10 AttributeError Raised in case of failure of attribute reference or assignment.
11 EOFError Raised when there is no input from either the raw_input() or input() function and the end of file is reached.
12 ImportError Raised when an import statement fails.
13 KeyboardInterrupt Raised when the user interrupts program execution, usually by pressing Ctrl+c.
14 LookupError Base class for all lookup errors.
15 IndexError Raised when an index is not found in a sequence.
16 KeyError Raised when the specified key is not found in the dictionary.
17 NameError Raised when an identifier is not found in the local or global namespace.
18 UnboundLocalError Raised when trying to access a local variable in a function or method but no value has been assigned to it.
19 EnvironmentError Base class for all exceptions that occur outside the Python environment.
20 IOError Raised when an input/ output operation fails, such as the print statement or the open() function when trying to open a file that does not exist.
21 IOError Raised for operating system-related errors.
22 SyntaxError Raised when there is an error in Python syntax.
23 IndentationError Raised when indentation is not specified properly.
24 SystemError Raised when the interpreter finds an internal problem, but when this error is encountered the Python interpreter does not exit.
25 SystemExit Raised when Python interpreter is quit by using the sys.exit() function. If not handled in the code, causes the interpreter to exit.
26 TypeError Raised when an operation or function is attempted that is invalid for the specified data type.
27 ValueError Raised when the built-in function for a data type has the valid type of arguments, but the arguments have invalid values specified.
28 RuntimeError Raised when a generated error does not fall into any category.
29 NotImplementedError Raised when an abstract method that needs to be implemented in an inherited class is not actually implemented.