In màu python 3

Dictionary Representation of A Graph Object:

{'data': [{'x': [1, 2, 3], 'y': [1, 3, 2], 'type': 'bar'}], 'layout': {'height': 600, 'width': 800}}



JSON Representation of A Graph Object:

{"data":[{"x":[1,2,3],"y":[1,3,2],"type":"bar"}],"layout":{"height":600,"width":800}}



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 tại hàm , 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à , và. 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;

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...")
...

Tuyên bố hoạt động như sau

  • Đầu tiên, mệnh đề try ((các) câu lệnh giữa từ khóa và từ khóa) đượ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 kết thúc

  • Nếu một ngoại lệ xảy ra trong khi thực hiện mệnh đề, 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, 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 bên ngoài;

Một câu lệnh có thể có nhiều hơn một mệnh đề ngoại trừ, để 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ột mệnh đề 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 là 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ự đó

class B(Exception):
    pass

class C(B):
    pass

class D(C):
    pass

for cls in [B, C, D]:
    try:
        raise cls()
    except D:
        print("D")
    except C:
        print("C")
    except B:
        print("B")

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

class B(Exception):
    pass

class C(B):
    pass

class D(C):
    pass

for cls in [B, C, D]:
    try:
        raise cls()
    except D:
        print("D")
    except C:
        print("C")
    except B:
        print("B")
2 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

class B(Exception):
    pass

class C(B):
    pass

class D(C):
    pass

for cls in [B, C, D]:
    try:
        raise cls()
    except D:
        print("D")
    except C:
        print("C")
    except B:
        print("B")
3 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
class B(Exception):
    pass

class C(B):
    pass

class D(C):
    pass

for cls in [B, C, D]:
    try:
        raise cls()
    except D:
        print("D")
    except C:
        print("C")
    except B:
        print("B")
4 để in tất cả các đối số mà không cần truy cập rõ ràng vào
class B(Exception):
    pass

class C(B):
    pass

class D(C):
    pass

for cls in [B, C, D]:
    try:
        raise cls()
    except D:
        print("D")
    except C:
        print("C")
    except B:
        print("B")
5

>>> try:
..     raise Exception('spam', 'eggs')
.. except Exception as inst:
..     print(type(inst))    # the exception instance
..     print(inst.args)     # arguments stored in .args
..     print(inst)          # __str__ allows args to be printed directly,
..                          # but may be overridden in exception subclasses
..     x, y = inst.args     # unpack args
..     print('x =', x)
..     print('y =', y)
...

('spam', 'eggs')
('spam', 'eggs')
x = spam
y = eggs

Đầu ra

class B(Exception):
    pass

class C(B):
    pass

class D(C):
    pass

for cls in [B, C, D]:
    try:
        raise cls()
    except D:
        print("D")
    except C:
        print("C")
    except B:
        print("B")
4 của ngoại lệ được in ở 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ý

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ó, , 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 thường không được xử lý, bởi vì chúng được sử dụng để chỉ ra rằng chương trình sẽ kết thúc. Chúng bao gồm cái nào được nâng lên và cái nào được nâng lên khi người dùng muốn làm gián đoạn chương trình

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ý 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ệ đó)

import sys

try:
    f = open('myfile.txt')
    s = f.readline()
    i = int(s.strip())
except OSError as err:
    print("OS error:", err)
except ValueError:
    print("Could not convert data to an integer.")
except Exception as err:
    print(f"Unexpected {err=}, {type(err)=}")
    raise

Câu lệnh … có một mệnh đề tùy chọn khác, khi xuất hiện, 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ụ

for arg in sys.argv[1:]:
    try:
        f = open(arg, 'r')
    except OSError:
        print('cannot open', arg)
    else:
        print(arg, 'has', len(f.readlines()), 'lines')
        f.close()

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

>>> try:
..     raise Exception('spam', 'eggs')
.. except Exception as inst:
..     print(type(inst))    # the exception instance
..     print(inst.args)     # arguments stored in .args
..     print(inst)          # __str__ allows args to be printed directly,
..                          # but may be overridden in exception subclasses
..     x, y = inst.args     # unpack args
..     print('x =', x)
..     print('y =', y)
...

('spam', 'eggs')
('spam', 'eggs')
x = spam
y = eggs
7 tốt hơn là thêm mã bổ sung vào mệnh đề vì nó tránh vô tình bắt gặp một ngoại lệ không được đưa ra bởi mã đang đượ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ụ

>>> def this_fails():
..     x = 1/0
...
>>> try:
..     this_fails()
.. except ZeroDivisionError as err:
..     print('Handling run-time error:', err)
...
Handling run-time error: division by zero

8. 4. Tăng ngoại lệ

Câu lệnh cho phép lập trình viên buộc một ngoại lệ cụ thể xảy ra. Ví dụ

>>> raise NameError('HiThere')
Traceback (most recent call last):
  File "", line 1, in 
NameError: HiThere

Đối số duy nhất để 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ừ , chẳng hạn như 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ó được đưa ra hay không nhưng không có ý định xử lý nó, thì một dạng câu lệnh đơn giản hơn sẽ 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 một phần, ngoại lệ đó sẽ đượ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 cho phép một mệnh đề 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ữ

import sys

try:
    f = open('myfile.txt')
    s = f.readline()
    i = int(s.strip())
except OSError as err:
    print("OS error:", err)
except ValueError:
    print("Could not convert data to an integer.")
except Exception as err:
    print(f"Unexpected {err=}, {type(err)=}")
    raise
9

>>> 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ơ học chuỗi, xem

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 thêm về các lớp Python). Các ngoại lệ thường được bắt nguồn từ lớp, 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 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ột mệnh đề, thì mệnh đề

for arg in sys.argv[1:]:
    try:
        f = open(arg, 'r')
    except OSError:
        print('cannot open', arg)
    else:
        print(arg, 'has', len(f.readlines()), 'lines')
        f.close()
2 sẽ thực thi như tác vụ cuối cùng trước khi câu lệnh hoàn thành. Mệnh đề
for arg in sys.argv[1:]:
    try:
        f = open(arg, 'r')
    except OSError:
        print('cannot open', arg)
    else:
        print(arg, 'has', len(f.readlines()), 'lines')
        f.close()
2 chạy dù câu lệnh
... except (RuntimeError, TypeError, NameError):
...     pass
2 có tạo ra 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 hiện mệnh đề

    ... except (RuntimeError, TypeError, NameError):
    ...     pass
    
    2, ngoại lệ đó có thể được xử lý bởi một mệnh đề. Nếu ngoại lệ không được xử lý bởi mệnh đề
    ... except (RuntimeError, TypeError, NameError):
    ...     pass
    
    4, thì ngoại lệ sẽ được đưa ra lại sau khi mệnh đề
    for arg in sys.argv[1:]:
        try:
            f = open(arg, 'r')
        except OSError:
            print('cannot open', arg)
        else:
            print(arg, 'has', len(f.readlines()), 'lines')
            f.close()
    
    2 đã đượ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
    >>> try:
    ..     raise Exception('spam', 'eggs')
    .. except Exception as inst:
    ..     print(type(inst))    # the exception instance
    ..     print(inst.args)     # arguments stored in .args
    ..     print(inst)          # __str__ allows args to be printed directly,
    ..                          # but may be overridden in exception subclasses
    ..     x, y = inst.args     # unpack args
    ..     print('x =', x)
    ..     print('y =', y)
    ...
    
    ('spam', 'eggs')
    ('spam', 'eggs')
    x = spam
    y = eggs
    
    7. Một lần nữa, ngoại lệ được đưa ra lại sau khi mệnh đề
    for arg in sys.argv[1:]:
        try:
            f = open(arg, 'r')
        except OSError:
            print('cannot open', arg)
        else:
            print(arg, 'has', len(f.readlines()), 'lines')
            f.close()
    
    2 đã được thực thi

  • Nếu mệnh đề

    for arg in sys.argv[1:]:
        try:
            f = open(arg, 'r')
        except OSError:
            print('cannot open', arg)
        else:
            print(arg, 'has', len(f.readlines()), 'lines')
            f.close()
    
    2 thực thi một câu lệnh , hoặc, các 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 , hoặc câu lệnh, thì mệnh đề
    for arg in sys.argv[1:]:
        try:
            f = open(arg, 'r')
        except OSError:
            print('cannot open', arg)
        else:
            print(arg, 'has', len(f.readlines()), 'lines')
            f.close()
    
    2 sẽ thực thi ngay trước khi câu lệnh
    >>> def this_fails():
    ..     x = 1/0
    ...
    >>> try:
    ..     this_fails()
    .. except ZeroDivisionError as err:
    ..     print('Handling run-time error:', err)
    ...
    Handling run-time error: division by zero
    
    5,
    >>> def this_fails():
    ..     x = 1/0
    ...
    >>> try:
    ..     this_fails()
    .. except ZeroDivisionError as err:
    ..     print('Handling run-time error:', err)
    ...
    Handling run-time error: division by zero
    
    6 hoặc
    >>> def this_fails():
    ..     x = 1/0
    ...
    >>> try:
    ..     this_fails()
    .. except ZeroDivisionError as err:
    ..     print('Handling run-time error:', err)
    ...
    Handling run-time error: division by zero
    
    7 được thực thi

  • Nếu mệnh đề

    for arg in sys.argv[1:]:
        try:
            f = open(arg, 'r')
        except OSError:
            print('cannot open', arg)
        else:
            print(arg, 'has', len(f.readlines()), 'lines')
            f.close()
    
    2 bao gồm câu lệnh
    >>> def this_fails():
    ..     x = 1/0
    ...
    >>> try:
    ..     this_fails()
    .. except ZeroDivisionError as err:
    ..     print('Handling run-time error:', err)
    ...
    Handling run-time error: division by zero
    
    7, thì giá trị được trả về sẽ là giá trị từ câu lệnh
    >>> def this_fails():
    ..     x = 1/0
    ...
    >>> try:
    ..     this_fails()
    .. except ZeroDivisionError as err:
    ..     print('Handling run-time error:', err)
    ...
    Handling run-time error: division by zero
    
    7 của mệnh đề
    for arg in sys.argv[1:]:
        try:
            f = open(arg, 'r')
        except OSError:
            print('cannot open', arg)
        else:
            print(arg, 'has', len(f.readlines()), 'lines')
            f.close()
    
    2, không phải giá trị từ câu lệnh
    >>> def this_fails():
    ..     x = 1/0
    ...
    >>> try:
    ..     this_fails()
    .. except ZeroDivisionError as err:
    ..     print('Handling run-time error:', err)
    ...
    Handling run-time error: division by zero
    
    7 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 đề được thực hiện trong mọi trường hợp. Việc tăng bằng cách chia hai chuỗi không được xử lý bởi mệnh đề và do đó được tăng lại sau khi mệnh đề

for arg in sys.argv[1:]:
    try:
        f = open(arg, 'r')
    except OSError:
        print('cannot open', arg)
    else:
        print(arg, 'has', len(f.readlines()), 'lines')
        f.close()
2 đã được thực thi

Trong các ứng dụng trong thế giới thực, mệnh đề này 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 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. Phát sinh 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 trang 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