Python cú pháp không hợp lệ

Cho đến nay các thông báo lỗi vẫn chưa được đề cập nhiều, nhưng nếu bạn đã thử các ví dụ thì có thể bạn đã thấy một số. Có (ít nhất) hai loại lỗi có thể phân biệt được. lỗi cú pháp và ngoại lệ

8. 1. Lỗi cú pháp¶

Lỗi cú pháp, còn được gọi là lỗi phân tích cú pháp, có lẽ là loại phàn nàn phổ biến nhất mà bạn nhận được khi vẫn đang học Python

>>> while True print('Hello world')
  File "", line 1
    while True print('Hello world')
                   ^
SyntaxError: invalid syntax

Trình phân tích cú pháp lặp lại dòng vi phạm và hiển thị một 'mũi tên' nhỏ chỉ vào điểm sớm nhất trong dòng mà lỗi được phát hiện. Lỗi là do (hoặc ít nhất là được phát hiện tại) mã thông báo trước mũi tên. trong ví dụ này, lỗi được phát hiện ở hàm

>>> while True:
..     try:
..         x = int(input("Please enter a number: "))
..         break
..     except ValueError:
..         print("Oops!  That was no valid number.  Try again...")
...
6, do dấu hai chấm (
>>> while True:
..     try:
..         x = int(input("Please enter a number: "))
..         break
..     except ValueError:
..         print("Oops!  That was no valid number.  Try again...")
...
7) bị thiếu trước nó. Tên tệp và số dòng được in để bạn biết tìm ở đâu trong trường hợp đầu vào đến từ tập lệnh

8. 2. Ngoại lệ¶

Ngay cả khi một câu lệnh hoặc biểu thức đúng về mặt cú pháp, nó vẫn có thể gây ra lỗi khi cố gắng thực hiện nó. Lỗi được phát hiện trong quá trình thực thi được gọi là ngoại lệ và không gây tử vong vô điều kiện. bạn sẽ sớm học cách xử lý chúng trong các chương trình Python. Tuy nhiên, hầu hết các trường hợp ngoại lệ không được xử lý bởi các chương trình và dẫn đến các thông báo lỗi như được hiển thị ở đây

>>> 10 * (1/0)
Traceback (most recent call last):
  File "", line 1, in 
ZeroDivisionError: division by zero
>>> 4 + spam*3
Traceback (most recent call last):
  File "", line 1, in 
NameError: name 'spam' is not defined
>>> '2' + 2
Traceback (most recent call last):
  File "", line 1, in 
TypeError: can only concatenate str (not "int") to str

Dòng cuối cùng của thông báo lỗi cho biết điều gì đã xảy ra. Các ngoại lệ có nhiều loại khác nhau và loại này được in như một phần của thông báo. các loại trong ví dụ là

>>> while True:
..     try:
..         x = int(input("Please enter a number: "))
..         break
..     except ValueError:
..         print("Oops!  That was no valid number.  Try again...")
...
8,
>>> while True:
..     try:
..         x = int(input("Please enter a number: "))
..         break
..     except ValueError:
..         print("Oops!  That was no valid number.  Try again...")
...
9 và
... except (RuntimeError, TypeError, NameError):
...     pass
0. Chuỗi được in dưới dạng loại ngoại lệ là tên của ngoại lệ tích hợp đã xảy ra. Điều này đúng với tất cả các ngoại lệ có sẵn, nhưng không nhất thiết phải đúng với các ngoại lệ do người dùng xác định (mặc dù đó là một quy ước hữu ích). Tên ngoại lệ tiêu chuẩn là số nhận dạng tích hợp (không phải từ khóa dành riêng)

Phần còn lại của dòng cung cấp chi tiết dựa trên loại ngoại lệ và nguyên nhân gây ra nó

Phần trước của thông báo lỗi hiển thị bối cảnh xảy ra ngoại lệ, ở dạng truy nguyên ngăn xếp. Nói chung, nó chứa một dòng nguồn liệt kê truy nguyên ngăn xếp;

Ngoại lệ tích hợp liệt kê các ngoại lệ tích hợp và ý nghĩa của chúng.

8. 3. Xử lý ngoại lệ¶

Có thể viết các chương trình xử lý các ngoại lệ đã chọn. Hãy xem ví dụ sau, ví dụ này yêu cầu người dùng nhập dữ liệu cho đến khi nhập một số nguyên hợp lệ, nhưng cho phép người dùng ngắt chương trình (sử dụng Control-C hoặc bất kỳ hệ điều hành nào hỗ trợ);

>>> while True:
..     try:
..         x = int(input("Please enter a number: "))
..         break
..     except ValueError:
..         print("Oops!  That was no valid number.  Try again...")
...

Câu lệnh

... except (RuntimeError, TypeError, NameError):
...     pass
2 hoạt động như sau

  • Đầu tiên, mệnh đề try ((các) câu lệnh nằm giữa từ khóa

    ... except (RuntimeError, TypeError, NameError):
    ...     pass
    
    2 và
    ... except (RuntimeError, TypeError, NameError):
    ...     pass
    
    4) được thực thi

  • Nếu không có ngoại lệ xảy ra, mệnh đề ngoại trừ bị bỏ qua và việc thực thi câu lệnh

    ... except (RuntimeError, TypeError, NameError):
    ...     pass
    
    2 kết thúc

  • Nếu một ngoại lệ xảy ra trong khi thực hiện mệnh đề

    ... except (RuntimeError, TypeError, NameError):
    ...     pass
    
    2, phần còn lại của mệnh đề sẽ bị bỏ qua. Sau đó, nếu loại của nó khớp với ngoại lệ được đặt tên theo từ khóa
    ... except (RuntimeError, TypeError, NameError):
    ...     pass
    
    4, thì mệnh đề ngoại trừ được thực thi và sau đó quá trình thực thi tiếp tục sau khối thử/ngoại trừ

  • Nếu một ngoại lệ xảy ra không khớp với ngoại lệ có tên trong mệnh đề ngoại trừ, nó sẽ được chuyển sang các câu lệnh

    ... except (RuntimeError, TypeError, NameError):
    ...     pass
    
    2 bên ngoài;

Một câu lệnh

... except (RuntimeError, TypeError, NameError):
...     pass
2 có thể có nhiều hơn một mệnh đề except, để chỉ định các trình xử lý cho các ngoại lệ khác nhau. Nhiều nhất một trình xử lý sẽ được thực thi. Trình xử lý chỉ xử lý các ngoại lệ xảy ra trong mệnh đề try tương ứng, không phải trong các trình xử lý khác của cùng một câu lệnh
... except (RuntimeError, TypeError, NameError):
...     pass
2. Ví dụ, một mệnh đề ngoại trừ có thể đặt tên cho nhiều ngoại lệ dưới dạng một bộ được đặt trong ngoặc đơn

... except (RuntimeError, TypeError, NameError):
...     pass

Một lớp trong mệnh đề

... except (RuntimeError, TypeError, NameError):
...     pass
4 tương thích với một ngoại lệ nếu nó là cùng một lớp hoặc một lớp cơ sở của nó (nhưng không phải ngược lại - một mệnh đề except liệt kê một lớp dẫn xuất không tương thích với một lớp cơ sở). Ví dụ: đoạn mã sau sẽ in B, C, D theo thứ tự đó

>>> while True:
..     try:
..         x = int(input("Please enter a number: "))
..         break
..     except ValueError:
..         print("Oops!  That was no valid number.  Try again...")
...
0

Lưu ý rằng nếu các mệnh đề ngoại trừ bị đảo ngược (với

>>> while True:
..     try:
..         x = int(input("Please enter a number: "))
..         break
..     except ValueError:
..         print("Oops!  That was no valid number.  Try again...")
...
02 trước), nó sẽ in ra B, B, B — mệnh đề ngoại trừ khớp đầu tiên được kích hoạt

Khi một ngoại lệ xảy ra, nó có thể có các giá trị liên quan, còn được gọi là đối số của ngoại lệ. Sự hiện diện và các loại đối số phụ thuộc vào loại ngoại lệ

Mệnh đề ngoại trừ có thể chỉ định một biến sau tên ngoại lệ. Biến được liên kết với thể hiện ngoại lệ thường có thuộc tính

>>> while True:
..     try:
..         x = int(input("Please enter a number: "))
..         break
..     except ValueError:
..         print("Oops!  That was no valid number.  Try again...")
...
03 lưu trữ các đối số. Để thuận tiện, các loại ngoại lệ dựng sẵn xác định
>>> while True:
..     try:
..         x = int(input("Please enter a number: "))
..         break
..     except ValueError:
..         print("Oops!  That was no valid number.  Try again...")
...
04 để in tất cả các đối số mà không cần truy cập rõ ràng vào
>>> while True:
..     try:
..         x = int(input("Please enter a number: "))
..         break
..     except ValueError:
..         print("Oops!  That was no valid number.  Try again...")
...
05

>>> while True:
..     try:
..         x = int(input("Please enter a number: "))
..         break
..     except ValueError:
..         print("Oops!  That was no valid number.  Try again...")
...
5

Đầu ra

>>> while True:
..     try:
..         x = int(input("Please enter a number: "))
..         break
..     except ValueError:
..         print("Oops!  That was no valid number.  Try again...")
...
04 của ngoại lệ được in dưới dạng phần cuối cùng ('chi tiết') của thông báo cho các ngoại lệ chưa được xử lý

>>> while True:
..     try:
..         x = int(input("Please enter a number: "))
..         break
..     except ValueError:
..         print("Oops!  That was no valid number.  Try again...")
...
07 là lớp cơ sở chung của tất cả các ngoại lệ. Một trong các lớp con của nó,
>>> while True:
..     try:
..         x = int(input("Please enter a number: "))
..         break
..     except ValueError:
..         print("Oops!  That was no valid number.  Try again...")
...
08, là lớp cơ sở của tất cả các ngoại lệ không nghiêm trọng. Các ngoại lệ không phải là lớp con của
>>> while True:
..     try:
..         x = int(input("Please enter a number: "))
..         break
..     except ValueError:
..         print("Oops!  That was no valid number.  Try again...")
...
08 thường không được xử lý, bởi vì chúng được sử dụng để chỉ ra rằng chương trình nên kết thúc. Chúng bao gồm
>>> while True:
..     try:
..         x = int(input("Please enter a number: "))
..         break
..     except ValueError:
..         print("Oops!  That was no valid number.  Try again...")
...
50 được tăng lên bởi
>>> while True:
..     try:
..         x = int(input("Please enter a number: "))
..         break
..     except ValueError:
..         print("Oops!  That was no valid number.  Try again...")
...
51 và
... except (RuntimeError, TypeError, NameError):
...     pass
1 được tăng lên khi người dùng muốn làm gián đoạn chương trình

>>> while True:
..     try:
..         x = int(input("Please enter a number: "))
..         break
..     except ValueError:
..         print("Oops!  That was no valid number.  Try again...")
...
08 có thể được sử dụng như một ký tự đại diện nắm bắt (hầu hết) mọi thứ. Tuy nhiên, cách tốt nhất là càng cụ thể càng tốt với các loại ngoại lệ mà chúng tôi dự định xử lý và cho phép mọi ngoại lệ không mong muốn lan truyền trên

Mẫu phổ biến nhất để xử lý

>>> while True:
..     try:
..         x = int(input("Please enter a number: "))
..         break
..     except ValueError:
..         print("Oops!  That was no valid number.  Try again...")
...
08 là in hoặc ghi nhật ký ngoại lệ rồi kích hoạt lại (cho phép người gọi cũng xử lý ngoại lệ đó)

>>> 10 * (1/0)
Traceback (most recent call last):
  File "", line 1, in 
ZeroDivisionError: division by zero
>>> 4 + spam*3
Traceback (most recent call last):
  File "", line 1, in 
NameError: name 'spam' is not defined
>>> '2' + 2
Traceback (most recent call last):
  File "", line 1, in 
TypeError: can only concatenate str (not "int") to str
5

Câu lệnh

... except (RuntimeError, TypeError, NameError):
...     pass
2 …
... except (RuntimeError, TypeError, NameError):
...     pass
4 có một mệnh đề tùy chọn khác, khi xuất hiện, mệnh đề này phải tuân theo tất cả các mệnh đề ngoại trừ. Nó hữu ích cho mã phải được thực thi nếu mệnh đề thử không đưa ra ngoại lệ. Ví dụ

>>> 10 * (1/0)
Traceback (most recent call last):
  File "", line 1, in 
ZeroDivisionError: division by zero
>>> 4 + spam*3
Traceback (most recent call last):
  File "", line 1, in 
NameError: name 'spam' is not defined
>>> '2' + 2
Traceback (most recent call last):
  File "", line 1, in 
TypeError: can only concatenate str (not "int") to str
8

Việc sử dụng mệnh đề

>>> while True:
..     try:
..         x = int(input("Please enter a number: "))
..         break
..     except ValueError:
..         print("Oops!  That was no valid number.  Try again...")
...
57 tốt hơn là thêm mã bổ sung vào mệnh đề
... except (RuntimeError, TypeError, NameError):
...     pass
2 vì nó tránh vô tình bắt gặp một ngoại lệ không được đưa ra bởi mã được bảo vệ bởi câu lệnh
... except (RuntimeError, TypeError, NameError):
...     pass
2 …
... except (RuntimeError, TypeError, NameError):
...     pass
4

Trình xử lý ngoại lệ không chỉ xử lý các ngoại lệ xảy ra ngay trong mệnh đề try mà còn xử lý cả những ngoại lệ xảy ra bên trong các hàm được gọi (thậm chí gián tiếp) trong mệnh đề try. Ví dụ

>>> while True:
..     try:
..         x = int(input("Please enter a number: "))
..         break
..     except ValueError:
..         print("Oops!  That was no valid number.  Try again...")
...
3

8. 4. Nâng cao ngoại lệ¶

Câu lệnh

>>> 10 * (1/0)
Traceback (most recent call last):
  File "", line 1, in 
ZeroDivisionError: division by zero
>>> 4 + spam*3
Traceback (most recent call last):
  File "", line 1, in 
NameError: name 'spam' is not defined
>>> '2' + 2
Traceback (most recent call last):
  File "", line 1, in 
TypeError: can only concatenate str (not "int") to str
51 cho phép lập trình viên buộc một ngoại lệ cụ thể xảy ra. Ví dụ

>>> while True:
..     try:
..         x = int(input("Please enter a number: "))
..         break
..     except ValueError:
..         print("Oops!  That was no valid number.  Try again...")
...
5

Đối số duy nhất của

>>> 10 * (1/0)
Traceback (most recent call last):
  File "", line 1, in 
ZeroDivisionError: division by zero
>>> 4 + spam*3
Traceback (most recent call last):
  File "", line 1, in 
NameError: name 'spam' is not defined
>>> '2' + 2
Traceback (most recent call last):
  File "", line 1, in 
TypeError: can only concatenate str (not "int") to str
51 chỉ ra ngoại lệ được nêu ra. Đây phải là một thể hiện ngoại lệ hoặc một lớp ngoại lệ (một lớp bắt nguồn từ
>>> while True:
..     try:
..         x = int(input("Please enter a number: "))
..         break
..     except ValueError:
..         print("Oops!  That was no valid number.  Try again...")
...
07, chẳng hạn như
>>> while True:
..     try:
..         x = int(input("Please enter a number: "))
..         break
..     except ValueError:
..         print("Oops!  That was no valid number.  Try again...")
...
08 hoặc một trong các lớp con của nó). Nếu một lớp ngoại lệ được thông qua, nó sẽ được khởi tạo hoàn toàn bằng cách gọi hàm tạo của nó mà không có đối số

>>> 10 * (1/0)
Traceback (most recent call last):
  File "", line 1, in 
ZeroDivisionError: division by zero
>>> 4 + spam*3
Traceback (most recent call last):
  File "", line 1, in 
NameError: name 'spam' is not defined
>>> '2' + 2
Traceback (most recent call last):
  File "", line 1, in 
TypeError: can only concatenate str (not "int") to str
0

Nếu bạn cần xác định xem một ngoại lệ đã được đưa ra nhưng không có ý định xử lý nó hay không, một dạng đơn giản hơn của câu lệnh

>>> 10 * (1/0)
Traceback (most recent call last):
  File "", line 1, in 
ZeroDivisionError: division by zero
>>> 4 + spam*3
Traceback (most recent call last):
  File "", line 1, in 
NameError: name 'spam' is not defined
>>> '2' + 2
Traceback (most recent call last):
  File "", line 1, in 
TypeError: can only concatenate str (not "int") to str
51 cho phép bạn đưa ra lại ngoại lệ đó

>>> 10 * (1/0)
Traceback (most recent call last):
  File "", line 1, in 
ZeroDivisionError: division by zero
>>> 4 + spam*3
Traceback (most recent call last):
  File "", line 1, in 
NameError: name 'spam' is not defined
>>> '2' + 2
Traceback (most recent call last):
  File "", line 1, in 
TypeError: can only concatenate str (not "int") to str
1

8. 5. Chuỗi ngoại lệ¶

Nếu một ngoại lệ chưa được xử lý xảy ra bên trong phần

... except (RuntimeError, TypeError, NameError):
...     pass
4, nó sẽ có ngoại lệ đang được xử lý kèm theo và được đưa vào thông báo lỗi

>>> 10 * (1/0)
Traceback (most recent call last):
  File "", line 1, in 
ZeroDivisionError: division by zero
>>> 4 + spam*3
Traceback (most recent call last):
  File "", line 1, in 
NameError: name 'spam' is not defined
>>> '2' + 2
Traceback (most recent call last):
  File "", line 1, in 
TypeError: can only concatenate str (not "int") to str
2

Để chỉ ra rằng một ngoại lệ là hệ quả trực tiếp của một ngoại lệ khác, câu lệnh

>>> 10 * (1/0)
Traceback (most recent call last):
  File "", line 1, in 
ZeroDivisionError: division by zero
>>> 4 + spam*3
Traceback (most recent call last):
  File "", line 1, in 
NameError: name 'spam' is not defined
>>> '2' + 2
Traceback (most recent call last):
  File "", line 1, in 
TypeError: can only concatenate str (not "int") to str
51 cho phép một mệnh đề
>>> 10 * (1/0)
Traceback (most recent call last):
  File "", line 1, in 
ZeroDivisionError: division by zero
>>> 4 + spam*3
Traceback (most recent call last):
  File "", line 1, in 
NameError: name 'spam' is not defined
>>> '2' + 2
Traceback (most recent call last):
  File "", line 1, in 
TypeError: can only concatenate str (not "int") to str
58 tùy chọn

>>> 10 * (1/0)
Traceback (most recent call last):
  File "", line 1, in 
ZeroDivisionError: division by zero
>>> 4 + spam*3
Traceback (most recent call last):
  File "", line 1, in 
NameError: name 'spam' is not defined
>>> '2' + 2
Traceback (most recent call last):
  File "", line 1, in 
TypeError: can only concatenate str (not "int") to str
3

Điều này có thể hữu ích khi bạn đang chuyển đổi ngoại lệ. Ví dụ

>>> 10 * (1/0)
Traceback (most recent call last):
  File "", line 1, in 
ZeroDivisionError: division by zero
>>> 4 + spam*3
Traceback (most recent call last):
  File "", line 1, in 
NameError: name 'spam' is not defined
>>> '2' + 2
Traceback (most recent call last):
  File "", line 1, in 
TypeError: can only concatenate str (not "int") to str
4

Nó cũng cho phép vô hiệu hóa chuỗi ngoại lệ tự động bằng cách sử dụng thành ngữ

>>> 10 * (1/0)
Traceback (most recent call last):
  File "", line 1, in 
ZeroDivisionError: division by zero
>>> 4 + spam*3
Traceback (most recent call last):
  File "", line 1, in 
NameError: name 'spam' is not defined
>>> '2' + 2
Traceback (most recent call last):
  File "", line 1, in 
TypeError: can only concatenate str (not "int") to str
59

>>> 10 * (1/0)
Traceback (most recent call last):
  File "", line 1, in 
ZeroDivisionError: division by zero
>>> 4 + spam*3
Traceback (most recent call last):
  File "", line 1, in 
NameError: name 'spam' is not defined
>>> '2' + 2
Traceback (most recent call last):
  File "", line 1, in 
TypeError: can only concatenate str (not "int") to str
5

Để biết thêm thông tin về cơ chế tạo chuỗi, hãy xem Ngoại lệ tích hợp sẵn .

8. 6. Ngoại lệ do người dùng định nghĩa¶

Các chương trình có thể đặt tên cho các ngoại lệ của riêng mình bằng cách tạo một lớp ngoại lệ mới (xem Lớp để biết thêm về các lớp Python). Các ngoại lệ thường được bắt nguồn từ lớp

>>> while True:
..     try:
..         x = int(input("Please enter a number: "))
..         break
..     except ValueError:
..         print("Oops!  That was no valid number.  Try again...")
...
08, trực tiếp hoặc gián tiếp.

Các lớp ngoại lệ có thể được định nghĩa để làm bất cứ điều gì mà bất kỳ lớp nào khác có thể làm, nhưng thường được giữ đơn giản, thường chỉ cung cấp một số thuộc tính cho phép trình xử lý trích xuất thông tin về lỗi cho ngoại lệ

Hầu hết các ngoại lệ được xác định với các tên kết thúc bằng “Lỗi”, tương tự như cách đặt tên cho các ngoại lệ tiêu chuẩn

Nhiều mô-đun tiêu chuẩn xác định các ngoại lệ của riêng chúng để báo cáo lỗi có thể xảy ra trong các chức năng mà chúng xác định

8. 7. Xác định hành động dọn dẹp¶

Câu lệnh

... except (RuntimeError, TypeError, NameError):
...     pass
2 có một mệnh đề tùy chọn khác nhằm xác định các hành động dọn dẹp phải được thực hiện trong mọi trường hợp. Ví dụ

>>> 10 * (1/0)
Traceback (most recent call last):
  File "", line 1, in 
ZeroDivisionError: division by zero
>>> 4 + spam*3
Traceback (most recent call last):
  File "", line 1, in 
NameError: name 'spam' is not defined
>>> '2' + 2
Traceback (most recent call last):
  File "", line 1, in 
TypeError: can only concatenate str (not "int") to str
6

Nếu có mệnh đề

>>> 10 * (1/0)
Traceback (most recent call last):
  File "", line 1, in 
ZeroDivisionError: division by zero
>>> 4 + spam*3
Traceback (most recent call last):
  File "", line 1, in 
NameError: name 'spam' is not defined
>>> '2' + 2
Traceback (most recent call last):
  File "", line 1, in 
TypeError: can only concatenate str (not "int") to str
82, mệnh đề
>>> 10 * (1/0)
Traceback (most recent call last):
  File "", line 1, in 
ZeroDivisionError: division by zero
>>> 4 + spam*3
Traceback (most recent call last):
  File "", line 1, in 
NameError: name 'spam' is not defined
>>> '2' + 2
Traceback (most recent call last):
  File "", line 1, in 
TypeError: can only concatenate str (not "int") to str
82 sẽ thực thi như tác vụ cuối cùng trước khi câu lệnh
... except (RuntimeError, TypeError, NameError):
...     pass
2 hoàn thành. Mệnh đề
>>> 10 * (1/0)
Traceback (most recent call last):
  File "", line 1, in 
ZeroDivisionError: division by zero
>>> 4 + spam*3
Traceback (most recent call last):
  File "", line 1, in 
NameError: name 'spam' is not defined
>>> '2' + 2
Traceback (most recent call last):
  File "", line 1, in 
TypeError: can only concatenate str (not "int") to str
82 chạy cho dù câu lệnh
... except (RuntimeError, TypeError, NameError):
...     pass
2 có tạo ngoại lệ hay không. Các điểm sau thảo luận về các trường hợp phức tạp hơn khi xảy ra ngoại lệ

  • Nếu một ngoại lệ xảy ra trong quá trình thực thi mệnh đề

    ... except (RuntimeError, TypeError, NameError):
    ...     pass
    
    2, ngoại lệ đó có thể được xử lý bởi mệnh đề
    ... except (RuntimeError, TypeError, NameError):
    ...     pass
    
    4. Nếu ngoại lệ không được xử lý bởi mệnh đề
    ... except (RuntimeError, TypeError, NameError):
    ...     pass
    
    4, ngoại lệ sẽ được đưa ra lại sau khi mệnh đề
    >>> 10 * (1/0)
    Traceback (most recent call last):
      File "", line 1, in 
    ZeroDivisionError: division by zero
    >>> 4 + spam*3
    Traceback (most recent call last):
      File "", line 1, in 
    NameError: name 'spam' is not defined
    >>> '2' + 2
    Traceback (most recent call last):
      File "", line 1, in 
    TypeError: can only concatenate str (not "int") to str
    
    82 đã được thực thi

  • Một ngoại lệ có thể xảy ra trong quá trình thực hiện mệnh đề

    ... except (RuntimeError, TypeError, NameError):
    ...     pass
    
    4 hoặc
    >>> while True:
    ..     try:
    ..         x = int(input("Please enter a number: "))
    ..         break
    ..     except ValueError:
    ..         print("Oops!  That was no valid number.  Try again...")
    ...
    
    57. Một lần nữa, ngoại lệ được đưa ra lại sau khi mệnh đề
    >>> 10 * (1/0)
    Traceback (most recent call last):
      File "", line 1, in 
    ZeroDivisionError: division by zero
    >>> 4 + spam*3
    Traceback (most recent call last):
      File "", line 1, in 
    NameError: name 'spam' is not defined
    >>> '2' + 2
    Traceback (most recent call last):
      File "", line 1, in 
    TypeError: can only concatenate str (not "int") to str
    
    82 đã được thực thi

  • Nếu mệnh đề

    >>> 10 * (1/0)
    Traceback (most recent call last):
      File "", line 1, in 
    ZeroDivisionError: division by zero
    >>> 4 + spam*3
    Traceback (most recent call last):
      File "", line 1, in 
    NameError: name 'spam' is not defined
    >>> '2' + 2
    Traceback (most recent call last):
      File "", line 1, in 
    TypeError: can only concatenate str (not "int") to str
    
    82 thực thi câu lệnh
    >>> while True:
    ..     try:
    ..         x = int(input("Please enter a number: "))
    ..         break
    ..     except ValueError:
    ..         print("Oops!  That was no valid number.  Try again...")
    ...
    
    35,
    >>> while True:
    ..     try:
    ..         x = int(input("Please enter a number: "))
    ..         break
    ..     except ValueError:
    ..         print("Oops!  That was no valid number.  Try again...")
    ...
    
    36 hoặc
    >>> while True:
    ..     try:
    ..         x = int(input("Please enter a number: "))
    ..         break
    ..     except ValueError:
    ..         print("Oops!  That was no valid number.  Try again...")
    ...
    
    37, các trường hợp ngoại lệ sẽ không được nêu lại

  • Nếu câu lệnh

    ... except (RuntimeError, TypeError, NameError):
    ...     pass
    
    2 đạt đến câu lệnh
    >>> while True:
    ..     try:
    ..         x = int(input("Please enter a number: "))
    ..         break
    ..     except ValueError:
    ..         print("Oops!  That was no valid number.  Try again...")
    ...
    
    35,
    >>> while True:
    ..     try:
    ..         x = int(input("Please enter a number: "))
    ..         break
    ..     except ValueError:
    ..         print("Oops!  That was no valid number.  Try again...")
    ...
    
    36 hoặc
    >>> while True:
    ..     try:
    ..         x = int(input("Please enter a number: "))
    ..         break
    ..     except ValueError:
    ..         print("Oops!  That was no valid number.  Try again...")
    ...
    
    37, thì mệnh đề
    >>> 10 * (1/0)
    Traceback (most recent call last):
      File "", line 1, in 
    ZeroDivisionError: division by zero
    >>> 4 + spam*3
    Traceback (most recent call last):
      File "", line 1, in 
    NameError: name 'spam' is not defined
    >>> '2' + 2
    Traceback (most recent call last):
      File "", line 1, in 
    TypeError: can only concatenate str (not "int") to str
    
    82 sẽ thực thi ngay trước khi thực thi câu lệnh
    >>> while True:
    ..     try:
    ..         x = int(input("Please enter a number: "))
    ..         break
    ..     except ValueError:
    ..         print("Oops!  That was no valid number.  Try again...")
    ...
    
    35,
    >>> while True:
    ..     try:
    ..         x = int(input("Please enter a number: "))
    ..         break
    ..     except ValueError:
    ..         print("Oops!  That was no valid number.  Try again...")
    ...
    
    36 hoặc
    >>> while True:
    ..     try:
    ..         x = int(input("Please enter a number: "))
    ..         break
    ..     except ValueError:
    ..         print("Oops!  That was no valid number.  Try again...")
    ...
    
    37

  • Nếu mệnh đề

    >>> 10 * (1/0)
    Traceback (most recent call last):
      File "", line 1, in 
    ZeroDivisionError: division by zero
    >>> 4 + spam*3
    Traceback (most recent call last):
      File "", line 1, in 
    NameError: name 'spam' is not defined
    >>> '2' + 2
    Traceback (most recent call last):
      File "", line 1, in 
    TypeError: can only concatenate str (not "int") to str
    
    82 bao gồm câu lệnh
    >>> while True:
    ..     try:
    ..         x = int(input("Please enter a number: "))
    ..         break
    ..     except ValueError:
    ..         print("Oops!  That was no valid number.  Try again...")
    ...
    
    37, thì giá trị được trả về sẽ là giá trị từ câu lệnh
    >>> while True:
    ..     try:
    ..         x = int(input("Please enter a number: "))
    ..         break
    ..     except ValueError:
    ..         print("Oops!  That was no valid number.  Try again...")
    ...
    
    37 của mệnh đề
    >>> 10 * (1/0)
    Traceback (most recent call last):
      File "", line 1, in 
    ZeroDivisionError: division by zero
    >>> 4 + spam*3
    Traceback (most recent call last):
      File "", line 1, in 
    NameError: name 'spam' is not defined
    >>> '2' + 2
    Traceback (most recent call last):
      File "", line 1, in 
    TypeError: can only concatenate str (not "int") to str
    
    82, không phải giá trị từ câu lệnh
    >>> while True:
    ..     try:
    ..         x = int(input("Please enter a number: "))
    ..         break
    ..     except ValueError:
    ..         print("Oops!  That was no valid number.  Try again...")
    ...
    
    37 của mệnh đề
    ... except (RuntimeError, TypeError, NameError):
    ...     pass
    
    2

Ví dụ

>>> 10 * (1/0)
Traceback (most recent call last):
  File "", line 1, in 
ZeroDivisionError: division by zero
>>> 4 + spam*3
Traceback (most recent call last):
  File "", line 1, in 
NameError: name 'spam' is not defined
>>> '2' + 2
Traceback (most recent call last):
  File "", line 1, in 
TypeError: can only concatenate str (not "int") to str
7

Một ví dụ phức tạp hơn

>>> 10 * (1/0)
Traceback (most recent call last):
  File "", line 1, in 
ZeroDivisionError: division by zero
>>> 4 + spam*3
Traceback (most recent call last):
  File "", line 1, in 
NameError: name 'spam' is not defined
>>> '2' + 2
Traceback (most recent call last):
  File "", line 1, in 
TypeError: can only concatenate str (not "int") to str
8

Như bạn có thể thấy, mệnh đề

>>> 10 * (1/0)
Traceback (most recent call last):
  File "", line 1, in 
ZeroDivisionError: division by zero
>>> 4 + spam*3
Traceback (most recent call last):
  File "", line 1, in 
NameError: name 'spam' is not defined
>>> '2' + 2
Traceback (most recent call last):
  File "", line 1, in 
TypeError: can only concatenate str (not "int") to str
82 được thực thi trong mọi trường hợp.
... except (RuntimeError, TypeError, NameError):
...     pass
0 được nâng lên bằng cách chia hai chuỗi không được xử lý bởi mệnh đề
... except (RuntimeError, TypeError, NameError):
...     pass
4 và do đó được tăng lại sau khi mệnh đề
>>> 10 * (1/0)
Traceback (most recent call last):
  File "", line 1, in 
ZeroDivisionError: division by zero
>>> 4 + spam*3
Traceback (most recent call last):
  File "", line 1, in 
NameError: name 'spam' is not defined
>>> '2' + 2
Traceback (most recent call last):
  File "", line 1, in 
TypeError: can only concatenate str (not "int") to str
82 đã được thực thi

Trong các ứng dụng trong thế giới thực, mệnh đề

>>> 10 * (1/0)
Traceback (most recent call last):
  File "", line 1, in 
ZeroDivisionError: division by zero
>>> 4 + spam*3
Traceback (most recent call last):
  File "", line 1, in 
NameError: name 'spam' is not defined
>>> '2' + 2
Traceback (most recent call last):
  File "", line 1, in 
TypeError: can only concatenate str (not "int") to str
82 rất hữu ích để giải phóng các tài nguyên bên ngoài (chẳng hạn như tệp hoặc kết nối mạng), bất kể việc sử dụng tài nguyên có thành công hay không

8. 8. Hành động dọn dẹp được xác định trước¶

Một số đối tượng xác định các hành động dọn dẹp tiêu chuẩn sẽ được thực hiện khi đối tượng không còn cần thiết, bất kể thao tác sử dụng đối tượng thành công hay thất bại. Hãy xem ví dụ sau, ví dụ này sẽ cố mở một tệp và in nội dung của nó ra màn hình

>>> 10 * (1/0)
Traceback (most recent call last):
  File "", line 1, in 
ZeroDivisionError: division by zero
>>> 4 + spam*3
Traceback (most recent call last):
  File "", line 1, in 
NameError: name 'spam' is not defined
>>> '2' + 2
Traceback (most recent call last):
  File "", line 1, in 
TypeError: can only concatenate str (not "int") to str
9

Vấn đề với mã này là nó để tệp mở trong một khoảng thời gian không xác định sau khi phần mã này thực thi xong. Đây không phải là vấn đề trong các tập lệnh đơn giản, nhưng có thể là vấn đề đối với các ứng dụng lớn hơn. Câu lệnh

>>> 10 * (1/0)
Traceback (most recent call last):
  File "", line 1, in 
ZeroDivisionError: division by zero
>>> 4 + spam*3
Traceback (most recent call last):
  File "", line 1, in 
NameError: name 'spam' is not defined
>>> '2' + 2
Traceback (most recent call last):
  File "", line 1, in 
TypeError: can only concatenate str (not "int") to str
07 cho phép các đối tượng như tệp được sử dụng theo cách đảm bảo chúng luôn được dọn dẹp kịp thời và chính xác

>>> while True:
..     try:
..         x = int(input("Please enter a number: "))
..         break
..     except ValueError:
..         print("Oops!  That was no valid number.  Try again...")
...
0

Sau khi câu lệnh được thực thi, tệp f luôn được đóng, ngay cả khi gặp sự cố khi xử lý các dòng. Các đối tượng, chẳng hạn như tệp, cung cấp các hành động dọn dẹp được xác định trước sẽ chỉ ra điều này trong tài liệu của chúng

8. 9. Tăng và xử lý nhiều ngoại lệ không liên quan¶

Có những tình huống cần phải báo cáo một số trường hợp ngoại lệ đã xảy ra. Điều này thường xảy ra trong các khung đồng thời, khi một số tác vụ có thể bị lỗi song song, nhưng cũng có những trường hợp sử dụng khác mà bạn nên tiếp tục thực thi và thu thập nhiều lỗi thay vì đưa ra ngoại lệ đầu tiên

Nội dung dựng sẵn

>>> 10 * (1/0)
Traceback (most recent call last):
  File "", line 1, in 
ZeroDivisionError: division by zero
>>> 4 + spam*3
Traceback (most recent call last):
  File "", line 1, in 
NameError: name 'spam' is not defined
>>> '2' + 2
Traceback (most recent call last):
  File "", line 1, in 
TypeError: can only concatenate str (not "int") to str
08 bao bọc một danh sách các trường hợp ngoại lệ để chúng có thể được nâng lên cùng nhau. Bản thân nó là một ngoại lệ, vì vậy nó có thể bị bắt như bất kỳ ngoại lệ nào khác

>>> while True:
..     try:
..         x = int(input("Please enter a number: "))
..         break
..     except ValueError:
..         print("Oops!  That was no valid number.  Try again...")
...
1

Bằng cách sử dụng

>>> 10 * (1/0)
Traceback (most recent call last):
  File "", line 1, in 
ZeroDivisionError: division by zero
>>> 4 + spam*3
Traceback (most recent call last):
  File "", line 1, in 
NameError: name 'spam' is not defined
>>> '2' + 2
Traceback (most recent call last):
  File "", line 1, in 
TypeError: can only concatenate str (not "int") to str
09 thay vì
... except (RuntimeError, TypeError, NameError):
...     pass
4, chúng tôi chỉ có thể xử lý có chọn lọc các ngoại lệ trong nhóm khớp với một loại nhất định. Trong ví dụ sau đây, cho thấy một nhóm ngoại lệ lồng nhau, mỗi mệnh đề
>>> 10 * (1/0)
Traceback (most recent call last):
  File "", line 1, in 
ZeroDivisionError: division by zero
>>> 4 + spam*3
Traceback (most recent call last):
  File "", line 1, in 
NameError: name 'spam' is not defined
>>> '2' + 2
Traceback (most recent call last):
  File "", line 1, in 
TypeError: can only concatenate str (not "int") to str
09 trích xuất một loại nhất định từ các ngoại lệ của nhóm trong khi để tất cả các ngoại lệ khác truyền sang các mệnh đề khác và cuối cùng được nâng cấp lại

>>> while True:
..     try:
..         x = int(input("Please enter a number: "))
..         break
..     except ValueError:
..         print("Oops!  That was no valid number.  Try again...")
...
2

Lưu ý rằng các ngoại lệ được lồng trong một nhóm ngoại lệ phải là các thể hiện, không phải kiểu. Điều này là do trong thực tế, các ngoại lệ thường là những ngoại lệ đã được chương trình nêu ra và bắt gặp, theo mẫu sau

>>> while True:
..     try:
..         x = int(input("Please enter a number: "))
..         break
..     except ValueError:
..         print("Oops!  That was no valid number.  Try again...")
...
3

8. 10. Làm giàu ngoại lệ bằng ghi chú¶

Khi một ngoại lệ được tạo để nâng lên, nó thường được khởi tạo với thông tin mô tả lỗi đã xảy ra. Có những trường hợp hữu ích khi thêm thông tin sau khi ngoại lệ bị bắt. Với mục đích này, các ngoại lệ có một phương thức

>>> 10 * (1/0)
Traceback (most recent call last):
  File "", line 1, in 
ZeroDivisionError: division by zero
>>> 4 + spam*3
Traceback (most recent call last):
  File "", line 1, in 
NameError: name 'spam' is not defined
>>> '2' + 2
Traceback (most recent call last):
  File "", line 1, in 
TypeError: can only concatenate str (not "int") to str
12 chấp nhận một chuỗi và thêm nó vào danh sách ghi chú của ngoại lệ. Kết xuất theo dõi tiêu chuẩn bao gồm tất cả các ghi chú, theo thứ tự chúng được thêm vào, sau ngoại lệ

>>> while True:
..     try:
..         x = int(input("Please enter a number: "))
..         break
..     except ValueError:
..         print("Oops!  That was no valid number.  Try again...")
...
4

Ví dụ: khi thu thập các ngoại lệ vào một nhóm ngoại lệ, chúng tôi có thể muốn thêm thông tin ngữ cảnh cho các lỗi riêng lẻ. Trong phần sau, mỗi ngoại lệ trong nhóm có một ghi chú cho biết khi lỗi này xảy ra