บทช่วยสอนนี้อธิบายการจัดการข้อยกเว้นใน Python โดยใช้บล็อก Try Except ด้วยความช่วยเหลือของตัวอย่างการเขียนโปรแกรม:
ข้อผิดพลาดสองประเภทอาจทำให้โปรแกรม Python หยุดทำงานกะทันหัน เช่น Syntax ข้อผิดพลาด และ ข้อยกเว้น ในบทช่วยสอนนี้ เราจะพูดถึงข้อผิดพลาดประเภทที่สอง (ข้อยกเว้น) ภายใต้หัวข้อที่สำคัญหลายหัวข้อ
เราจะได้รับประโยชน์มากมายจากการจัดการข้อยกเว้นในแอปพลิเคชันของเรา เช่น:
- การสร้างแอปพลิเคชันที่มีประสิทธิภาพ
- การสร้างโค้ดที่สะอาดและปราศจากข้อผิดพลาด
Python ลองยกเว้น
ข่าวดีอย่างหนึ่งคือ Python มีข้อยกเว้นในตัวจำนวนมากเพื่อตรวจจับข้อผิดพลาดในโค้ดของเรา นอกจากนี้ยังเปิดโอกาสให้เราสร้างข้อยกเว้นที่กำหนดเองได้เมื่อไม่มีข้อยกเว้นในตัวที่ตรงกับความต้องการของเรา
ข้อยกเว้นคืออะไร
ข้อยกเว้นใน Python คืออะไร พูดง่ายๆ ก็คือ เมื่อใดก็ตามที่ตัวแปลภาษา Python พยายามเรียกใช้โค้ดที่ไม่ถูกต้อง จะเกิดข้อยกเว้นขึ้น และในกรณีที่ไม่มีการจัดการข้อยกเว้นดังกล่าว ก็จะรบกวนการทำงานปกติของคำสั่งของโปรแกรมและพิมพ์การย้อนกลับ
มาสร้างโค้ดที่ไม่ถูกต้องและดูว่าตัวแปล Python จะตอบสนองอย่างไร
เปิด Python shell และรันโค้ดต่อไปนี้
>>> 50/0
นี่เป็นหนึ่งใน ข้อผิดพลาดที่พบบ่อยที่สุดในการเขียนโปรแกรม โค้ดด้านบนพยายามหารตัวเลข 50 ด้วย 0 (ศูนย์) งูเหลือมตัวแปร openFile ก่อนที่จะถูกกำหนด
เคล็ดลับเล็กๆ น้อยๆ ที่นี่คือการใช้ตัวจัดการข้อยกเว้นภายในบล็อกสุดท้าย
def readFile(file_path): try: openFile = open(file_path,'r') # Open a file as read-only print(openFile.readline()) # Read first line of file content except FileNotFoundError as ex: print(ex) finally: try: print("Cleaning...") openFile.close() except: # catches all exceptions pass # Ignore this error because we don't care. if __name__ == '__main__': filePath = './text.txt' readFile(filePath)
หาก try-block ของเราเพิ่ม FileNotFoundError เราจะได้ผลลัพธ์ต่อไปนี้
เพิ่มข้อยกเว้น
ข่าวดีอย่างหนึ่งเกี่ยวกับข้อยกเว้นของ Python คือเราสามารถจงใจ เลี้ยงดูพวกเขา ข้อยกเว้นถูกยกขึ้นด้วย คำสั่งยก .
คำสั่งยกมีไวยากรณ์ต่อไปนี้:
raise [ExceptionName[(*args: Object)]]
เปิดเทอร์มินัลและยกวัตถุข้อยกเว้นจาก ข้อยกเว้นในตัวของ Python ตัวอย่างเช่น ถ้าเราเพิ่ม ZeroDivisionError:
>>> raise ZeroDivisionError("Can't divide by zero")
เราจะได้รับการตรวจสอบย้อนกลับ:
ดังนั้น ทำไมการเพิ่มข้อยกเว้นจึงสำคัญ
- เมื่อทำงานกับข้อยกเว้นที่กำหนดเอง
- ในระหว่างการตรวจสอบสติ
คลาสข้อยกเว้นที่กำหนดเอง
ข้อยกเว้นแบบกำหนดเองคือข้อยกเว้นที่คุณสร้างขึ้นเพื่อจัดการกับข้อผิดพลาดที่เฉพาะเจาะจงกับความต้องการของคุณ เคล็ดลับคือ เรากำหนดคลาสที่มาจากออบเจกต์ ข้อยกเว้น จากนั้นเราใช้คำสั่ง Raise เพื่อยกระดับคลาสข้อยกเว้นของเรา
สมมติว่าเราต้องการตรวจสอบอินพุตของผู้ใช้และตรวจสอบให้แน่ใจว่า ค่าอินพุตไม่เป็นค่าลบ (ตรวจสอบสุขภาพจิต) แน่นอน เราสามารถเพิ่มข้อยกเว้นของ Python ValueError ได้ แต่เราต้องการปรับแต่งข้อผิดพลาดโดยตั้งชื่อที่เจาะจงและอธิบายตนเอง เช่น InputIsNegativeError แต่ข้อยกเว้นนี้ไม่ใช่ Python ในตัวข้อยกเว้น
ก่อนอื่น เราสร้างคลาสพื้นฐานของเราซึ่งจะมาจากข้อยกเว้น
class CustomError(Exception): "Base class exception for all exceptions of this module" pass
จากนั้นเราสร้างคลาสข้อยกเว้นที่จะสืบทอดคลาสพื้นฐานและจะจัดการกับข้อผิดพลาดเฉพาะของเรา
class InputIsNegativeError(CustomError): """Raised when User enters a negative value""" pass
มาทดสอบกัน
try: value = int(input()) if value 0: raise InputIsNegativeError # Raise exception if value is negative except InputIsNegativeError: # catch and handle exception print("Input value shouldn't be negative")
คำขอโค้ดข้างต้นสำหรับอินพุตของผู้ใช้ และตรวจสอบว่าเป็นค่าลบหรือไม่ ถ้าเป็นจริง จะทำให้เกิดข้อยกเว้นที่กำหนดเองของเรา InputIsNegativeError ซึ่งพบในภายหลังในคำสั่งยกเว้น
ด้านล่างคือโค้ดที่สมบูรณ์:
class CustomError(Exception): "Base class exception for all exceptions of this module" pass class InputIsNegativeError(CustomError): """Raised when User enters a negative value""" pass if __name__ == '__main__': try: value = int(input("Input a number: ")) if value 0: raise InputIsNegativeError # Raise exception if value is negative except InputIsNegativeError: # catch and handle exception print("Input value shouldn't be negative")
หากค่าอินพุต เป็นจำนวนลบเช่น -1 จากนั้นเราจะได้ผลลัพธ์:
ลองดูเอกสาร Python สำหรับรายละเอียดเพิ่มเติมเกี่ยวกับข้อยกเว้นที่กำหนดเองของ Python
คำถามที่พบบ่อย
Q #1) Python จัดการกับข้อยกเว้นอย่างไร
คำตอบ: Python จัดการกับข้อยกเว้นโดยใช้ปุ่ม คำสั่งลองยกเว้น รหัสที่สามารถทำให้เกิดข้อยกเว้นจะถูกวางและดำเนินการใน บล็อกลอง ในขณะที่ บล็อกยกเว้น เก็บโค้ดที่จะจัดการกับข้อยกเว้นหากมีสิ่งใดเกิดขึ้น
คำถาม #2) อะไรทำให้เกิดข้อยกเว้นใน Python?
คำตอบ: เมื่อใดก็ตามที่ตัวแปลภาษา Python พบรหัสที่ไม่ถูกต้อง จะทำให้เกิดข้อยกเว้น ซึ่งเป็นวิธีการของ Python เอง เพื่อบอกเราว่ามีเรื่องไม่คาดฝันเกิดขึ้น เรายังสามารถจงใจยกข้อยกเว้นโดยใช้ คำสั่งยก .
คำถาม #3) Python จัดการกับข้อยกเว้นหลายข้อได้อย่างไร
คำตอบ: Python จัดการกับข้อยกเว้นหลายข้อโดยใช้บล็อกยกเว้นเดี่ยวหรือหลายบล็อกยกเว้น
สำหรับบล็อกเดียว ข้อยกเว้นจะถูกส่งผ่านเป็นทูเพิล: ยกเว้น (Exception1, Exception2,..,ExceptionN) และการตรวจสอบ Python สำหรับการแข่งขันจากขวาไปซ้าย ในกรณีนี้ การดำเนินการเดียวกันสำหรับแต่ละข้อยกเว้น
อีกวิธีหนึ่งในการตรวจจับข้อยกเว้นทั้งหมดคือการไม่ใส่ชื่อข้อยกเว้นไว้หลังคำหลักยกเว้น
except: # handle all exceptions here
วิธีที่สองคือ เพื่อใช้บล็อกยกเว้นสำหรับแต่ละข้อยกเว้น:
except Exception1: # code to handle Exception1 goes here except Exception2: # code to handle Exception2 goes here except ExceptionN: # code to handle ExceptionN goes here
วิธีนี้ คุณสามารถดำเนินการแยกต่างหากสำหรับแต่ละข้อยกเว้น
Q #4) เหตุใดการจัดการข้อยกเว้นจึงสำคัญใน Python
คำตอบ: ประโยชน์ของการจัดการข้อยกเว้นใน Python คือเราสามารถสร้างแอปพลิเคชันที่มีประสิทธิภาพ สะอาด และปราศจากข้อผิดพลาด เราไม่ต้องการให้รหัสการผลิตของเราล้มเหลวเนื่องจากข้อผิดพลาดบางอย่าง ดังนั้นเราจึงจัดการกับข้อผิดพลาดและทำให้แอปพลิเคชันของเราทำงานอยู่เสมอ
คำถาม #5) คุณจะเพิกเฉยต่อข้อยกเว้นใน Python ได้อย่างไร
คำตอบ: หากต้องการละเว้นข้อยกเว้นใน Python ให้ใช้คีย์เวิร์ด ผ่าน ในบล็อกยกเว้น สมมติว่าเราต้องการละเว้นข้อยกเว้น ValueError เราจะดำเนินการดังนี้:
except ValueError: pass
หากคุณไม่ทราบว่ากำลังทำอะไรอยู่ การเพิกเฉยต่อข้อยกเว้นถือเป็นแนวทางปฏิบัติที่ไม่ดี อย่างน้อย แจ้งให้ผู้ใช้ทราบเกี่ยวกับข้อผิดพลาดที่อาจเกิดขึ้นทั้งหมด
บทสรุป
ในบทช่วยสอนนี้ เราได้กล่าวถึง: ข้อยกเว้นของ Python, Traceback; วิธีจัดการกับข้อยกเว้นด้วย Try / Except / Else / Finally การบล็อก วิธี ยก ข้อยกเว้น และสุดท้าย วิธีสร้างข้อยกเว้นที่กำหนดเอง
ขอบคุณที่อ่าน!
ล่ามเห็นว่านี่เป็นการดำเนินการที่ไม่ถูกต้อง และเพิ่ม ZeroDivisionErrorขัดขวางโปรแกรม และพิมพ์การย้อนกลับ
เราจะเห็นได้อย่างชัดเจนว่า ZeroDivisionError เป็นข้อยกเว้นที่เกิดขึ้น มันเป็นวิธีของ Python ที่จะบอกเราว่ามันไม่เจ๋งที่จะหารตัวเลขด้วยศูนย์ แม้ว่าในภาษาอื่นๆ เช่น JavaScript นี่ไม่ใช่ข้อผิดพลาด และไพธอนห้ามการปฏิบัติเช่นนี้อย่างเคร่งครัด
นอกจากนี้ สิ่งสำคัญคือต้องรู้ว่านี่เป็นเพียงออบเจกต์ข้อยกเว้น และ Python มีออบเจกต์ดังกล่าวในตัวมากมาย ดูเอกสารอย่างเป็นทางการของ Python นี้เพื่อดูข้อยกเว้นในตัวของ Python ทั้งหมด
ทำความเข้าใจเกี่ยวกับ Traceback
ก่อนที่เราจะจัดการข้อยกเว้น ฉันคิดว่าจะช่วยให้เข้าใจว่าจะเกิดอะไรขึ้นหากมีข้อยกเว้น ไม่ได้รับการจัดการ และวิธีที่ Python ทำได้ดีที่สุดเพื่อแจ้งให้เราทราบเกี่ยวกับข้อผิดพลาดของเรา
เมื่อใดก็ตามที่ Python พบข้อผิดพลาด จะทำให้เกิดข้อยกเว้นขึ้น หากไม่มีการจัดการข้อยกเว้นนี้ ก็จะสร้างข้อมูลบางอย่างที่เรียกว่า Traceback ดังนั้น การย้อนกลับนี้มีข้อมูลใดบ้าง
ประกอบด้วย:
- ข้อความแสดงข้อผิดพลาดที่บอกเราว่ามีข้อยกเว้นใดบ้างและเกิดอะไรขึ้นก่อนเกิดข้อยกเว้นนี้ ยกขึ้น
- หมายเลขบรรทัดต่างๆ ของรหัสที่ทำให้เกิดข้อผิดพลาดนี้ ข้อผิดพลาดอาจเกิดจากลำดับการเรียกใช้ฟังก์ชันที่เรียกว่า call stack ซึ่งเราจะพูดถึงในภายหลัง
แม้ว่าจะเป็นเราสัญญาว่าตัวอย่างต่อไปจะทำให้เราเข้าใจมากขึ้น
เรียกคืนการย้อนกลับที่พิมพ์จากการหาร 50 ด้วย 0 ด้านบน เราจะเห็นว่าการย้อนกลับมีข้อมูลต่อไปนี้:
- ไฟล์ “”: สิ่งนี้บอกเราว่ารหัสนี้ถูกเรียกใช้จากเทอร์มินัลคอนโซล
- บรรทัดที่ 1: สิ่งนี้บอกเราว่าข้อผิดพลาดเกิดขึ้นในหมายเลขบรรทัดนี้
- ZeroDivisionError: การหารด้วย ศูนย์: เป็นการบอกเราว่าข้อยกเว้นใดเกิดขึ้นและอะไรเป็นสาเหตุ
ลองอีกตัวอย่างหนึ่งและ อาจดูว่า call stack มีลักษณะอย่างไร เปิดตัวแก้ไข ป้อนรหัสด้านล่างและบันทึกเป็น tracebackExp .py
def stack1(numb): # 1 div = 0 # 2 stack2(numb, div) # 3 def stack2(numb, div): # 5 compute = numb/div # 6 print(compute) # 7 if __name__ == '__main__': # 9 numb = 5 # 10 stack1(numb) # 11
เปิดเทอร์มินัลในไดเร็กทอรีที่พบไฟล์นี้และเรียกใช้
python tracebackExp.py
คุณจะเห็นการย้อนกลับต่อไปนี้:
การย้อนกลับด้านบนอาจดูสับสน แต่จริงๆ แล้วไม่ใช่ Pythonistas คิดวิธีที่ดีที่สุดในการอ่านการย้อนกลับ ซึ่งมาจาก จากล่างขึ้นบน ดังนั้น ลองใช้ความรู้นี้เพื่อพยายามทำความเข้าใจว่าการย้อนกลับนี้มีให้อะไรบ้าง
- ด้านล่างสุด เราได้รับข้อยกเว้นที่ยกขึ้นมาและเหตุใดจึงถูกยกขึ้น
- เลื่อนขึ้น เราได้รับชื่อไฟล์ tracebackExp .py เมื่อข้อผิดพลาดนี้เกิดขึ้น การคำนวณที่ทำให้เกิดข้อผิดพลาดนี้ compute = ชา/div ฟังก์ชัน stack2 และหมายเลขลิงก์ บรรทัดที่ 6 ที่ดำเนินการคำนวณนี้ .
- เลื่อนขึ้น เราจะเห็นว่าฟังก์ชัน stack2 ของเราถูกเรียกในฟังก์ชัน stack1 ในบรรทัดที่ 3
- เมื่อย้ายไปที่ด้านบนสุด เราจะเห็นว่ามีการเรียกฟังก์ชัน stack1 ในบรรทัดที่ 11 โมดูล > บอกเราว่าเป็นไฟล์ที่กำลังดำเนินการ
ข้อยกเว้น Python ทั่วไป
ไลบรารี Python กำหนดข้อยกเว้นในตัวจำนวนมาก คุณสามารถตรวจสอบเอกสาร Python หรือเรียกใช้ฟังก์ชัน local () ในตัวดังต่อไปนี้:
>>> dir(locals()['__builtins__'])
เราจะไม่พยายามแก้ไขข้อยกเว้นเหล่านี้ทั้งหมด แต่เราจะเห็นข้อยกเว้นทั่วไปบางประการ ที่คุณน่าจะเจอ
#1) TypeError
จะเกิดขึ้นเมื่อมีการใช้การดำเนินการหรือฟังก์ชันกับวัตถุประเภทที่ไม่เหมาะสม
ตัวอย่างที่ 1
พิจารณาโปรแกรมด้านล่าง มันรับเงินปันผลและตัวหาร จากนั้นคำนวณและพิมพ์ผลลัพธ์ของการหารเงินปันผลด้วยตัวหาร
def compute_division(): dividend = int(input("Enter the dividend: ")) # cast string to int divisor = input("Enter the divisor: ") # no casting # Compute division result = dividend/divisor # print result print("The result of {}/{} is: {}".format(dividend, divisor, result)) if __name__ == '__main__': result = compute_division()
เราขอมูลค่าของเงินปันผลและตัวหารจากผู้ใช้ แต่เราลืมที่จะโยนสตริงของตัวหาร ค่าเป็นจำนวนเต็ม ดังนั้นเราจึงลงเอยด้วยประเภทของเงินปันผลที่เป็นจำนวนเต็ม ( int ) และประเภทของตัวหารเป็นสตริง ( str ) จากนั้นเราจะได้รับ TypeError เนื่องจากตัวดำเนินการหาร (/) ไม่ทำงานบนสตริง
คุณอาจสนใจที่จะรู้ว่าไม่เหมือนกับ Python Javascript มี Type Coercion ซึ่งจะแปลงหนึ่งในประเภทของตัวถูกดำเนินการให้เป็นค่าที่เทียบเท่ากับประเภทของตัวถูกดำเนินการอื่นๆ เมื่อตัวถูกดำเนินการเป็นของประเภทต่างๆ
#2) ValueError
สิ่งนี้จะเกิดขึ้นเมื่อการดำเนินการหรือฟังก์ชันได้รับอาร์กิวเมนต์ที่มีประเภทที่ถูกต้องแต่มีค่าที่ไม่เหมาะสม
ตัวอย่าง 2
พิจารณาโปรแกรมของเราใน ตัวอย่างที่ 1 ด้านบน
หากผู้ใช้ป้อนค่าที่เป็นตัวอักษรและตัวเลขสำหรับเงินปันผล เช่น '3a' โปรแกรมของเราจะเพิ่ม ข้อยกเว้น ValueError นี่เป็นเพราะแม้ว่าเมธอด Python int() จะรับตัวเลขหรือสตริงใดๆ และส่งคืนออบเจกต์จำนวนเต็ม แต่ค่าสตริงไม่ควรมีตัวอักษรหรือค่าใดๆ ที่ไม่ใช่ตัวเลข
#3) AttributeError
ข้อยกเว้นนี้เกิดขึ้นขณะกำหนดหรืออ้างอิงแอตทริบิวต์ที่ไม่มีอยู่
ตัวอย่างที่ 3
พิจารณาโปรแกรม ด้านล่าง. ใช้ตัวเลขและคำนวณรากที่สองโดยใช้โมดูลคณิตศาสตร์ Python
import math # import math library to gain access to its code def compute_square_root(number): # compute the square root using the math library result = math.sqr(number) return result if __name__ == '__main__': # get input to compute from user number = int(input("Compute Square root of: ")) # call function to compute square root
เมื่อผู้ใช้ป้อนตัวเลข โปรแกรมของเราจะพยายามใช้ฟังก์ชันจากโมดูลคณิตศาสตร์เพื่อคำนวณรากที่สอง แต่ในที่นี้ เราทำผิดพลาด แทนที่จะพิมพ์ sqrt เราพิมพ์ sqr ที่ไม่มีอยู่ในโมดูลคณิตศาสตร์ผิดพลาด
ดังนั้นเราจึงพยายามอ้างอิงแอตทริบิวต์ sqr ที่ไม่มีอยู่จริงและนำ ข้อยกเว้น AttributeError ถูกยกขึ้น พวกเราส่วนใหญ่ทำผิดพลาดแบบนี้บ่อยมาก ดังนั้น คุณไม่ได้อยู่คนเดียว
การจัดการข้อยกเว้นด้วยการลองยกเว้น
ในฐานะโปรแกรมเมอร์ สิ่งหนึ่งที่พวกเราส่วนใหญ่จะใช้เวลากับการเขียนโค้ดที่มีประสิทธิภาพนั่นคือยืดหยุ่น. รหัสที่ไม่เสียหายเนื่องจากข้อผิดพลาดบางอย่าง ใน Python เราสามารถทำได้โดยการใส่คำสั่งของเราไว้ใน ลอง – ยกเว้น คำสั่ง
คำสั่ง Python Try-Except
คำสั่ง try-except มีโครงสร้างดังต่อไปนี้:
try: #your code goes here except """Specify exception type(s) here""": #handle exception here
ใส่โค้ดใน tracebackExp .py ไว้ในคำสั่ง try-except
def stack1(numb): # 1 div = 0 # 2 stack2(numb, div) # 3 def stack2(numb, div): # 5 try: # 6 compute = numb/div # 7 print(compute) # 8 except ZeroDivisionError as zde: # 9 print(zde) # 10 if __name__ == '__main__': # 12 numb = 5 # 13 stack1(numb) # 14 print("program continuous") # 15
การรันโค้ดนี้จะสร้างเอาต์พุต
นี่คือวิธีการทำงานของคำสั่ง try-except Python รันโค้ดในบล็อกลอง บรรทัดที่ 7-8 หากไม่พบรหัสที่ไม่ถูกต้อง ดังนั้นรหัสในบล็อกยกเว้น บรรทัดที่ 10 จะถูกข้ามและดำเนินการต่อไป
แต่หากพบรหัสที่ไม่ถูกต้อง การดำเนินการจะหยุดทันทีใน ลองบล็อกและตรวจสอบว่าข้อยกเว้นที่เกิดขึ้นนั้นตรงกับที่เราให้ไว้ในคำสั่งยกเว้น บรรทัดที่ 9 หรือไม่ หากตรงกันบล็อกยกเว้นจะถูกดำเนินการและดำเนินการต่อ ถ้าไม่เป็นเช่นนั้น โปรแกรมจะขัดจังหวะ
โดยปกติแล้ว try-block จะมีโค้ดที่อาจสร้างข้อยกเว้นในขณะที่บล็อกยกเว้นจะจับและจัดการกับข้อยกเว้น
การจัดการหลายรายการ ข้อยกเว้นที่มีข้อยกเว้น
เราสามารถจัดการข้อยกเว้นหลายรายการได้ด้วย "ข้อยกเว้น" เดียวหรือ "ยกเว้น" หลายรายการ ทั้งหมดขึ้นอยู่กับวิธีที่คุณต้องการจัดการกับข้อยกเว้นแต่ละข้อ
#1) การจัดการข้อยกเว้นหลายรายการด้วยข้อยกเว้นเดียว
try: #your code goes here except(Exception1[, Exception2[,...ExceptionN]]]): #handle exception here
วิธีนี้ใช้เมื่อเราสงสัยว่าโค้ดของเราอาจเพิ่มข้อยกเว้นที่แตกต่างกันและเราต้องการดำเนินการเดียวกันในแต่ละกรณี ดังนั้น หากตัวแปล Python พบการจับคู่ โค้ดที่เขียนในบล็อกยกเว้นจะดำเนินการ
ลองพิจารณาตัวอย่างโค้ด Python ด้านล่าง
def get_fraction(value, idx): arr = [4,5,2,0] # a list of numbers idx_value = arr[idx] # if idx is > arr length, IndexError will be raised value/idx_value # if idx_value == 0, ZeroDivisionError will be raised if __name__ =='__main__': # set 'value' and 'idx' value = 54 idx = 3 # call function in a try-except statement. try: result = get_fraction(value, idx) print("Fraction is ", result) except (IndexError, ZeroDivisionError) as ex: print(ex)
เรามีสอง ข้อยกเว้นที่เป็นไปได้ที่สามารถยกขึ้นที่นี่ ZeroDivisionError และ IndexError หากมีข้อยกเว้นเหล่านี้เกิดขึ้น บล็อกยกเว้นจะถูกดำเนินการ
ในโค้ดด้านบน idx=3 ดังนั้น idx_ value จะกลายเป็น 0 และ value /idx_ value จะเพิ่ม ZeroDivisionError
#2) การจัดการข้อยกเว้นหลายรายการด้วยข้อยกเว้นหลายรายการ
try: #your code goes here except Exception1: #handle exception1 here except Exception2: #handle exception2 here except ExceptionN: #handle exceptionN here
หากเราต้องการจัดการมากกว่า แต่ละข้อยกเว้นแยกจากกัน นี่คือวิธีที่คุณสามารถทำได้
พิจารณาตัวอย่างโค้ด Python ด้านล่าง
def get_fraction(value, idx): arr = [4,5,2,0] # a list of numbers idx_value = arr[idx] # if idx is > arr length, IndexError will be raised value/idx_value # if idx_value == 0, ZeroDivisionError will be raised if __name__ =='__main__': # set 'value' and 'idx' value = 54 idx = 5 # call function in a try-excepts statement. try: result = get_fraction(value, idx) print("Fraction is ", result) except IndexError: print("idx of {} is out of range".format(idx)) except ZeroDivisionError: print("arr[{}] is 0. Hence, can't divide by zero".format(idx)) except Exception as ex: print(ex) print("Not sure what happened so not safe to continue, \ app will be interrupted") raise ex
เราสังเกตเห็นว่าข้อยกเว้นถูกใช้ในคำสั่งยกเว้นสุดท้าย . นี่เป็นเพราะวัตถุยกเว้น ข้อยกเว้น ตรงกับข้อยกเว้นใดๆ ด้วยเหตุผลนี้ มันควรจะเป็นตัวสุดท้ายเสมอ เนื่องจาก Python จะหยุดตรวจสอบตัวจัดการข้อยกเว้นอื่นๆ เมื่อตัวจัดการหนึ่งตัวตรงกัน
ในโค้ดด้านบน idx=5 ดังนั้น arr[idx ] จะเพิ่ม IndexError เนื่องจาก idx มากกว่าความยาวของรายการ arr
นอกจากนี้ ไม่แน่ใจว่าแอปพลิเคชันของคุณยกข้อยกเว้นใดขึ้นมาจะไม่ปลอดภัยที่จะดำเนินการต่อไป นั่นเป็นเหตุผลที่เรามีประเภท ข้อยกเว้น เพื่อตรวจจับข้อยกเว้นที่ไม่คาดคิด จากนั้นเราจึงแจ้งให้ผู้ใช้และขัดจังหวะแอปพลิเคชันโดยเพิ่มข้อยกเว้นเดียวกัน
ลองใช้คำสั่งอื่น
นี่เป็น คุณลักษณะทางเลือก ของการจัดการข้อยกเว้น และอนุญาตให้คุณเพิ่มรหัสที่คุณต้องการ เรียกใช้เมื่อไม่มีข้อผิดพลาดเกิดขึ้น ถ้าเกิดข้อผิดพลาด บล็อก else นี้จะไม่ทำงาน
พิจารณาตัวอย่างโค้ด Python ที่ด้านล่าง เปิดโปรแกรมแก้ไขและบันทึกโค้ดเป็น elseTry.py
def fraction_of_one(divisor): value = 1/divisor # if divisor is zero, ZeroDivisionError will be raised return value if __name__ == '__main__': while True: try: # Get input from the user. # if input is not a valid argument for int(), ValueError will be raised divisor = int(input("Enter a divisor: ")) # call our function to compute the fraction value = fraction_of_one(divisor) except (ValueError, ZeroDivisionError): print("Input can't be zero and should be a valid literal for int(). Please, try again!") else: print("Value: ", value) break
เราได้รับอินพุตจากผู้ใช้และใช้เพื่อหาร 1 เรามีข้อยกเว้นที่เป็นไปได้สองประการที่นี่ การป้อนข้อมูลของผู้ใช้ที่ไม่ถูกต้องซึ่งจะทำให้เกิด ValueError และ ศูนย์(0) ซึ่งจะทำให้เกิด ZeroDivisionError . คำสั่งยกเว้นของเราจัดการกับข้อผิดพลาดเหล่านี้
ตอนนี้ เราต้องการพิมพ์ค่าของ ค่า บล็อกอื่นของเราทำให้แน่ใจว่าพิมพ์ออกมาก็ต่อเมื่อบล็อกการลองของเราดำเนินการโดยไม่มีข้อผิดพลาด นี่เป็นสิ่งสำคัญเนื่องจากหากเกิดข้อผิดพลาดในบล็อกการพยายามของเรา ค่า จะไม่ได้กำหนด ดังนั้น การเข้าถึงจะทำให้เกิดข้อผิดพลาดขึ้นอีก
เรียกใช้โค้ดด้านบนด้วย Python elseTry.py
ผลลัพธ์ด้านบนแสดงว่า สำหรับอินพุตแรก เราพิมพ์ 0 แล้วกด ENTER เนื่องจากตัวหารของเราได้รับ 0, 1/ตัวหารยก ศูนย์DivisionError อินพุตที่สองของเราคือ k ซึ่งไม่ถูกต้องสำหรับ int () ดังนั้นจึงมีข้อยกเว้น ValueError
แต่อินพุตสุดท้ายของเราคือ 9 ซึ่งถูกต้องและเป็น a ผลลัพธ์ เราได้ค่า “ value ” พิมพ์เป็น 0.1111111111111111
ลองสุดท้ายคำชี้แจง
นี่เป็น คุณลักษณะเสริม ของการจัดการข้อยกเว้น และจะทำงานเสมอไม่ว่าจะเกิดอะไรขึ้นในตัวจัดการข้อยกเว้น
นั่นคือ:
- มีข้อยกเว้นเกิดขึ้นหรือไม่
- แม้ว่าจะมีการเรียกใช้ 'return' ในบล็อกอื่นๆ
- แม้ว่าสคริปต์จะปิดในบล็อกอื่นๆ
ดังนั้น หากเรามีโค้ดที่เราต้องการเรียกใช้ในทุกสถานการณ์ สุดท้ายแล้วบล็อคก็คือคนของเรา บล็อกนี้ส่วนใหญ่ใช้สำหรับการล้างข้อมูล เช่น การปิดไฟล์
พิจารณาตัวอย่างโค้ด Python ด้านล่าง
def readFile(file_path): try: openFile = open(file_path,'r') # Open a file as read-only print(openFile.readline()) # Read first line of file content except FileNotFoundError as ex: print(ex) finally: print("Cleaning...") openFile.close() if __name__ == '__main__': filePath = './text.txt' readFile(filePath)
โค้ดนี้พยายามเปิดและอ่านไฟล์ text.txt ในไดเรกทอรีปัจจุบัน หากมีไฟล์อยู่ โปรแกรมของเราจะพิมพ์บรรทัดแรกของไฟล์ จากนั้นบล็อกสุดท้ายของเราจะทำงานและปิดไฟล์
สมมติว่าเรามีไฟล์ชื่อ text.txt ในไดเร็กทอรีที่ไฟล์โปรแกรมนี้ คือและประกอบด้วยสวัสดี ถ้าเราเรียกใช้โปรแกรม เราจะมีผลลัพธ์
ตัวอย่างนี้ถูกเลือกโดยเจตนาเพราะฉันต้องการให้เราแก้ไขปัญหาเล็กน้อยที่อาจเกิดขึ้นเมื่อปิดไฟล์ในที่สุด- block.
หากไม่มีไฟล์ ข้อยกเว้น FileNotFoundError จะถูกยกขึ้น และตัวแปร openFile จะไม่ถูกกำหนดและไม่เป็นไฟล์ วัตถุ. ดังนั้น การพยายามปิดในบล็อกสุดท้ายจะทำให้เกิดข้อยกเว้น UnboundLocalError ซึ่งเป็นคลาสย่อยของ NameError
โดยพื้นฐานแล้วจะบอกว่าเรากำลังพยายามอ้างอิง เดอะ