Python cho người khác cuối cùng

Hôm ni, mình học tiếp về bạn “Lỗi và ngoại lệ”, bài blog tiếp theo nằm trong series “Khám phá Đại Bản Doanh Python”, thuộc phần Python Tutorial nha

Ở bài này, mình sẽ đi tìm hiểu các loại lỗi và ngoại lệ trong Python cũng như cách xử lý và tạo ngoại lệ riêng của mình.

[Những nội dung trong loạt bài này từ chủ yếu mình lấy từ python. org rồi viết lại hoặc dịch lại theo ngôn ngữ của mình]

Nếu bạn đọc từ đầu sê-ri đến đây, chắc chắn là bạn đã thấy vài đoạn mã mình cố tình ví dụ cho nó xuất hiện lỗi, trong bài “I/O trong Python”

Hình trên cho mình thấy có hai loại lỗi có thể phân biệt được, đó là. “lỗi cú pháp” và “lỗi cú pháp“

Syntax error

Lỗi cú pháp là lỗi xảy ra khi phân tích cú pháp, là loại lỗi của mình hay gặp nhất.

Trình phân tích cú pháp sẽ lặp lại dòng bị lỗi và hiển thị một dấu mũi tên nhỏ tạo vị trí là thời điểm sớm nhất trong dòng nơi lỗi được phát hiện.

Ở ví dụ về thể hiện lỗi được phát hiện tại vị trí hàm in được gọi, lý do là thiếu dấu “. ”

Đôi khi cú pháp lỗi nhưng không có vị trí nào được phát hiện, ví dụ như ở đầu bài “SyntaxError. đối số vị trí theo sau đối số từ khóa” can to show the variable by the position before the variable in the key

Ngoại lệ

Ngay cả khi cú pháp đã đúng, mã vẫn có thể gây ra lỗi trong quá trình thực thi. Những lỗi phát sinh trong quá trình thực thi mã được gọi là ngoại lệ

Như bạn thấy ở ngoại lệ có nhiều loại khác nhau và sẽ có thông tin lỗi kèm theo.

Ở ví dụ trên, nhóm mình có các ngoại lệ như “ZeroDivisionError“, “NameError“, “TypeError“

Xử lý ngoại lệ

Khi viết chương trình với Python, đôi khi mình sẽ cố gắng ngoại lệ để xử lý chúng. Như ví dụ dưới đây, đầu vào được nhập từ phía người dùng có thể gây ra ngoại lệ “ValueErrror” và mình xử lý bằng cách gửi thông tin cho người dùng biết họ đã nhập sai

At ví dụ trên đã sử dụng nhóm lệnh “thử…ngoại trừ” để bắt và sử dụng ngoại lệ

Đoạn mã trên hoạt động như sau

– Đầu tiên, mã trong mệnh đề “thử” được thực hiện

– Nếu không có ngoại lệ xảy ra, bỏ mệnh đề “ngoại trừ” sẽ bị loại bỏ và kết thúc chương trình [như khi mình nhập 9]

– Nếu có ngoại lệ xảy ra trong lúc thực thi mã định mệnh trong đề thử thì các đoạn mã bên dưới nó sẽ bị loại bỏ. Nếu lỗi ngoại lệ trùng với lỗi mình bắt[sau từ khóa “ngoại trừ”, ở đây là ValueError], thì đoạn mã trong ngoại trừ sẽ được thực thi[trong ra “Rất tiếc. …”]. And the code phase in try will going to going to be done

– Ngoài ra, nếu ngoại lệ xảy ra nhưng không trùng với ngoại lệ mình đã bắt, chương trình sẽ dừng lại và trong ngoại lệ ra màn hình [ngoại lệ chưa được xử lý]

Vì có thể có nhiều ngoại lệ xảy ra nên

– một “thử” có thể đi cùng với nhiều “ngoại trừ”. hay sử dụng khi mình muốn xử lý từng thứ trừ nhau

– một ngoại trừ có thể bắt nhiều loại ngoại lệ, ví dụ. ngoại trừ [RuntimeError, TypeError]. hay sử dụng khi mình muốn gom nhiều loại ngoại trừ vào sử dụng một lần

Xegrade nào đến trước

Có hai đoạn mã như hai hình dưới đây, cùng dự đoán thứ tự khi ra hai ví dụ 1, 2 được thực thi nhé 😀

Lưu ý là “RotDH_NV1” được mở rộng từ lớp Ngoại lệ

Bạn nghiên cứu kỹ chưa, đã dự đoán thứ tự ra ở hai ví dụ là gì chưa nhỉ?

Trước khi phỏng vấn, hãy thử đưa ra kết quả của mình trước nha

Đây là câu trả lời của mình, để mình thử coi đúng không hen

Đầu tiên là thứ tự kế thừa của mấy bạn này

Ngoại lệ > RotDH_NV1 > RotDH_NV2 > RotDH_NV3

Như vậy là khi vòng lặp thực thi từng đối tượng

ví dụ 1

– nâng RotDH_NV1 thì kiểm tra

-> trùng với ngoại trừ RotDH_NV3 -> Sai, đi tiếp

-> trùng với ngoại trừ RotDH_NV2 -> Sai, đi tiếp

-> trùng với ngoại trừ RotDH_NV1 -> True, go in ra “RotDH_NV1“

– nâng RotDH_NV2 thì kiểm tra

-> trùng với ngoại trừ RotDH_NV3 -> Sai, đi tiếp

-> trùng với ngoại trừ RotDH_NV2 -> True, go in ra “RotDH_NV2“

– nâng RotDH_NV3 thì kiểm tra

-> trùng với ngoại trừ RotDH_NV3 -> True, go in ra “RotDH_NV3“

In the result in the example 1 is

XoayDH_NV1

XoayDH_NV2

XoayDH_NV3

**Ví dụ 2. **

– nâng RotDH_NV1 thì kiểm tra

-> trùng với ngoại trừ RotDH_NV1 -> True, go in ra “RotDH_NV1“

– nâng RotDH_NV2 thì kiểm tra

-> trùng với ngoại trừ RotDH_NV1 -> True, go in ra “RotDH_NV1“

– nâng RotDH_NV3 thì kiểm tra

-> trùng với ngoại trừ RotDH_NV1 -> True, go in ra “RotDH_NV1“

The result in ra at example 2 is

XoayDH_NV1

XoayDH_NV1

XoayDH_NV1

Từ ví dụ trên, mình thấy được khi có ngoại lệ được nâng lên, đụng bạn nào là bạn ấy thực thi trước, nó cũng giống như công việc cấp cứu vậy, xe cấp cứu nào đến trước thì chở người ta đi bệnh viện trước

Đôi khi sẽ có lỗi xảy ra nhưng mình không đoán được loại ngoại lệ đó là gì, và mình thường xử lý “ngoại trừ. ” không đi kèm với các loại ngoại lệ nào, để thu thập đủ mấy bạn còn lại

Tuy nhiên, hãy nhớ cẩn thận khi sử dụng bạn này nha, vì bạn ấy đã bắt cả bóng rổ nên sẽ dễ dàng phát hiện ra lỗi của chương trình và gây khó khăn cho việc kiểm tra lỗi

Làm vậy, tốt nhất là nên dùng bạn ấy cho bọn còn lại, lỗi ra ngoài và nâng lại bạn ấy lên để biết rằng chủ động bảo vệ mã nha.

Làm ri nè. bắt coi mặt mũi tên lỗi ra sao rồi nâng lỗi lên lại để cho bạn gặp lỗi ngoài ý muốn không cứ thế mà im lặng lơ đi

except:
      print[‘Lỗi chi mà hông rõ nè”, sys.exc_info[][0]]
      raise

Đoạn ni cho mình lưu ý xí nữa nha. You are any or used “ngoại trừ Exception as e. ” để bắt các ngoại lệ còn lại phải không?

Khi mình xài cái “ngoại trừ Exception as e. ” thì có cái tiện là mình có thể truy cập vào các thuộc tính của đối tượng thay đổi “e” as e. tin nhắn hay e. tranh luận

Nhưng bạn lưu ý tí là cái “ngoại trừ Exception như e. ” nó khác với cái “ngoại trừ. ” nha. Tools

- "ngoại trừ. ” bắt tất cả các ngoại lệ

– “ngoại trừ Ngoại lệ. ” hoặc “ngoại trừ Ngoại lệ như e. ” bắt tất cả các loại ngoại lệ nhưng TRỪ “BaseException”, “SystemExist”, “KeyboardInterupt” và “GeneratorExist”[Có nghĩa là các bạn bị trừ đi này vẫn la làng chứ không im lặng đâu nha]

Làm cho tôi điều này nếu không bị loại trừ bất kỳ ngoại lệ nào [Làm điều đó nếu không có ngoại lệ tăng]

Ngoài ra, nhóm “thử … ngoại trừ” còn có một mệnh đề đi kèm không bắt buộc là “khác”, đi sau tất cả các loại “ngoại trừ”

Mệnh đề này thường bao gồm các đoạn mã cần thực thi nếu mệnh đề thử không có bất kỳ ngoại lệ nào

try:
   # code cần thực thi
except OSError:
   # xử lý ngoại lệ OSError
else:
   # thực thi đoạn này dù ngoại lệ có bị bắt hay không

Sử dụng mệnh đề khác như trên thì tốt hơn so với việc bỏ đoạn mã cần thực hiện điều đó luôn luôn trong mệnh đề cố gắng như thế này

try:
   # code cần thực thi
   # thực thi đoạn này dù ngoại lệ có bị bắt hay không
except OSError:
   # xử lý ngoại lệ OSError

Drawer NGOẠI LỆ

Khi ngoại lệ xảy ra, bạn ấy có một vài giá trị để thể hiện mình, kiểu như mình tên gì, nhà ở đâu hay gia đình có mấy người ý, mấy bạn này hay được gọi với tên anh là “lập luận của ngoại lệ”

Mình đã từng nhắc đến các bạn này ở đoạn “ngoại trừ Exception as e” có e. message and e. args ý ạ

Ngoài ra mấy bạn mặc định được trả ra như trên, thì khi mình nâng cao ngoại lệ, mình cũng có thể truyền cho bạn những giá trị cụ thể như sau. “tăng Ngoại lệ[“giá trị 1”, “giá trị 2″]”

Để thuận tiện, các giá trị được truyền vào mặc định này sẽ được trả ra khi khởi động hàm tạo

try:
   # code cần thực thi
except OSError:
   # xử lý ngoại lệ OSError
else:
   # thực thi đoạn này dù ngoại lệ có bị bắt hay không
0 của ngoại lệ, vì vậy khi gọi print[e] của e trong “ngoại trừ ngoại lệ là e” thì nó có giá trị là [“ . or e. args cũng có giá trị như trên

La làng khi có ngoại lệ

Ở các nội dung trên, rất nhiều lần bọn mình đã từng là làng khi mã có vấn đề, bạn đã biết cách làng khi có ngoại lệ rồi phải không?

Đó chính là sử dụng cuộc gọi cấp cứu 115 =]]

Mình đùa thôi, đó là dùng từ khóa “nâng” đi kèm với ngoại lệ hoặc đi một mình mình cũng được

Down error

Ha ha, bạn có tin ngoại lệ lỗi cho nhau không?

If you want, it was. Đó là một

Đây là ví dụ cho sự đổ lỗi, hay gọi hoa mỹ hơn là các ngoại lệ được xâu chuỗi với nhau, mời bạn xem đoạn mã này

Ở trên, rõ ràng là ngoại lệ IOError bị bắt, nhưng mình cố gắng thay đổi tình trạng lỗi thành RuntimeError bằng cách sử dụng “từ”, cú pháp giúp mình có thể xâu chuỗi lỗi IOError qua lỗi RuntimeError và trong cả hai bạn, màn hình này hiển thị như trên

Nhưng nếu bạn chỉ muốn gặp lỗi “RuntimError” thôi, và không muốn xuất hiện lỗi IOError nữa, thì bạn có thể sử dụng “từ Không” để vô hiệu hóa quá trình ngoại lệ chuỗi của bạn từ

Khi đó nó sẽ làm việc như thế này

Yeah, vậy là đám mình có thể đổi lỗi trắng trợn mà không truy xuất được nguồn gốc luôn [ngoại trừ khi nhìn mã vô]

Đương nhiên, bạn này khá nguy hiểm vì đổi tứ tung lên cả lại làm khó khi gỡ lỗi đó, nên thận trọng khi sử dụng thì hơn

Ngoại lệ của mình

Giờ đó[ý là từ đầu bài tới chậm], mình làm việc với ngoại lệ của người ta[ngoại lệ mặc định của Python], giờ mình thích cũng tạo ra ngoại lệ của riêng mình rồi, đơn giản là nói tiếng người, á

Khi mình viết chương trình của mình, mình có thể tạo ra ngoại lệ bằng cách kế thừa từ lớp “Ngoại lệ”, cả bằng cách trực tiếp và gián tiếp

Trực tiếp thì khỏi giải thích ha, còn gián tiếp là mình kế thừa từ bạn ngoại lệ nào kế thừa từ “Exception”, hoai

Thông thường, người ta hay tạo ra một ngoại lệ cơ sở kế thừa trực tiếp, rồi những loại ngoại lệ khác kế thừa gián tiếp “Ngoại lệ” bằng một ngoại lệ cơ sở đó

À, còn về cách đặt tên, họ cũng đặt tên theo cùng họ luôn, ví dụ họ ở đây có thể là Error. Input Error, StupidError, NevermindError, … Type vậy á 😀

Mọi người cùng dự đoán qua ví dụ nha

Làm cho tôi điều này với bất kỳ giá nào [Làm bất kể điều gì]

Ở phần “Làm cho tôi điều này nếu không bị loại bỏ ngoại lệ nào”, cậu mình xài “khác” sau khi trừ á khẩu, nhớ hông, đó là mình thực thi mã khi không có ngoại lệ xảy ra

Còn đây, là “Làm cho tôi điều này bất cứ giá nào”, thì mình dùng với “cuối cùng”, đó là mình thực thi đám code trong finally dù có ngoại lệ xảy ra hay không

Tức giận là đoạn mã ở cuối cùng cái này có thể cái nào cũng phải làm, họ gọi là mát mẻ là “hành động dọn dẹp”

Mời bạn xem ví dụ nha

Bạn thắc mắc tại sao lại gặp ngoại lệ mà đoạn in vẫn không được?

Đó là cơ chế của cuối cùng đó, cùng mình tìm hiểu thêm về cách hoạt động của bạn nào

Nếu mệnh đề “cuối cùng” xuất hiện, thì mệnh đề thuộc mệnh đề này sẽ thực thi như là công việc cuối cùng trước khi lệnh try end

Dưới đây là cơ chế hoạt động cho những vấn đề khá phức tạp cuối cùng

– Nếu có ngoại lệ xảy ra khi thực thi nhóm lệnh trong “thử”, nếu ngoại lệ là làng lên nhưng chưa bị bắt lại bằng “ngoại trừ”, thì nhóm lệnh trong “cuối cùng” vẫn chạy trước, sau đó ngoại lệ mới

– If have a NGOẠI LỆ Xảy ra do command group in except or other. Một lần nữa, lệnh nhóm trong cuối cùng đã được chạy trước sau đó ngoại lệ trong đám phát sinh này mới được la làng lên

– Nếu khối lệnh trong try có các lệnh được đặt cụ thể như “break”, “continue” hay “return” làm dừng thi giữa chừng thì nhóm lệnh trong cuối cùng cũng thực hiện trước khi đám đông này được gọi

– Nếu khối lệnh trong finally có chứa lệnh “return” thì giá trị trả về sẽ là giá trị từ cuối cùng chứ không phải giá trị trả về từ mã khối trong lần thử

Trong thực tế, cuối cùng là nơi chứa các nhóm lệnh phục vụ cho việc giải phóng các tài nguyên như tệp hay các kết nối mạng, bất kể các tài nguyên này được sử dụng hay không

Một vài ví dụ thú vị về cuối cùng đây ạ

>>> def bool_return[]:
..   try:
..      return True
..   finally:
..      return False
...
>>> bool_return[]
False
>>> def divide[x, y]:
..     try:
..         result = x / y
..     except ZeroDivisionError:
..         print["division by zero!"]
..     else:
..         print["result is", result]
..     finally:
..         print["executing finally clause"]
...
>>> divide[2, 1]
result is 2.0
executing finally clause
>>> divide[2, 0]
division by zero!
executing finally clause
>>> divide["2", "1"]
executing finally clause
Traceback [most recent call last]:
  File "", line 1, in 
  File "", line 3, in divide
TypeError: unsupported operand type[s] for /: 'str' and 'str'

Này, hãy nhớ xem bạn cuối cùng trước khi đi tiếp nha

Dòm lại lần nữa coi có hiểu ví dụ không?

Định nghĩa trước công việc làm sạch

Trong Python, có một vài loại đối tượng được định nghĩa sẵn các hành động làm sạch để trả lại tài nguyên khi mình không sử dụng nữa mà không cần biết tài nguyên đó có được sử dụng thành công hay không [như khi chính ta thực hiện làm

Loại đối tượng như vậy có thể kể từ điển hình là khi mình làm việc với một tập tin

Thường thì khi mình mở một file mình sẽ dùng open[“filename. txt”]. Vấn đề ở đây là bọn mình mở người ta rồi nhưng không nhớ mà đóng lại để thu hồi tài nguyên bộ nhớ về, và có thể gây ra vấn đề về bộ nhớ cho các project lớn hoặc file quá nặng

Với lệnh “with” cho phép các đối tượng như tệp có thể đảm bảo bộ nhớ sẽ được giải nén mỗi khi thực hiện đoạn mã thi xong nằm trong nhóm lệnh này. Do đó đảm bảo tài nguyên được thu hồi ngược thời gian và chính xác

Chủ Đề