Python3 exceptionprocessingtutorial

Learning Python3 in exceptionprocessingmechanism, includingerror捕获, processing and 自定义exception

exceptionprocessing basicconcepts

exception is 程序执行过程in发生 error, 它会in断程序 正常执行流程. in Pythonin, exception is aobject, 表示程序执行过程in发生 error or exceptioncircumstances.

当Python程序遇 to error时, 会抛出一个exception. such as果不processing这个exception, 程序会终止并显示errorinformation. throughexceptionprocessing, 我们可以捕获并processing这些exception, 使程序able to继续执行.

common Pythonexceptionincluding:

try-except语句

try-except语句 is Pythonin用于捕获 and processingexception basicstructure. 它 语法such as under :

try:
    # 可能会引发exception code
    pass
except [ExceptionType [as e]]:
    # processingexception code
    pass

try块in code引发exception时, Python会跳转 to for 应 except块in执行exceptionprocessingcode.

basic用法

# basic exceptionprocessing
try:
    num = int(input("请输入一个number: "))
    result = 10 / num
    print(f"结果 is : {result}")
except:
    print("发生了error!")

捕获specificexception

我们可以指定要捕获 specificexceptionclass型, 这样只 has 当引发 exception is 指定class型 or 其子class时, 才会执行 for 应 except块.

# 捕获specificexception
try:
    num = int(input("请输入一个number: "))
    result = 10 / num
    print(f"结果 is : {result}")
except ValueError:
    print("输入error, 请输入一个 has 效 number!")
except ZeroDivisionError:
    print("error: 除数不能 for 零!")
except Exception as e:
    print(f"发生了othererror: {e}")

捕获 many 个exception

我们可以 in 一个except块in捕获 many 个exceptionclass型, 将它们放 in 一个元组in.

# 捕获 many 个exception
try:
    num = int(input("请输入一个number: "))
    result = 10 / num
    print(f"结果 is : {result}")
except (ValueError, ZeroDivisionError) as e:
    print(f"发生了error: {e}")

else and finally子句

else子句

else子句会 in try块in code没 has 引发exception时执行.

# usingelse子句
try:
    num = int(input("请输入一个number: "))
    result = 10 / num
except ValueError:
    print("输入error, 请输入一个 has 效 number!")
except ZeroDivisionError:
    print("error: 除数不能 for 零!")
else:
    print(f"计算成功, 结果 is : {result}")
finally:
    print("程序执行完毕. ")

finally子句

finally子句无论try块 is 否引发exception都会执行, 通常用于执行cleanoperation, such as关闭file, 释放resourceetc..

# usingfinally子句
try:
    f = open("example.txt", "r")
    content = f.read()
    print(content)
except FileNotFoundError:
    print("file未找 to !")
finally:
    # 无论 is 否发生exception, 都会执行这里 code
    if 'f' in locals() and not f.closed:
        f.close()
        print("file已关闭. ")

# usingwith语句 (更简洁 方式) 
try:
    with open("example.txt", "r") as f:
        content = f.read()
        print(content)
except FileNotFoundError:
    print("file未找 to !")
# with语句会自动关闭file, 不需要finally子句

抛出exception

我们可以usingraise语句手动抛出exception. 这 in 以 under circumstances under 很 has 用:

# 手动抛出exception
def divide(a, b):
    if b == 0:
        raise ZeroDivisionError("除数不能 for 零!")
    return a / b

try:
    result = divide(10, 0)
    print(f"结果 is : {result}")
except ZeroDivisionError as e:
    print(f"捕获 to exception: {e}")

我们也可以重 new 抛出exception, 将exception传递给 on 层调用者:

# 重 new 抛出exception
def process_data(data):
    try:
        # processingdata
        if not data:
            raise ValueError("data for 空!")
        return len(data)
    except ValueError as e:
        print(f"processingdata时发生error: {e}")
        # 重 new 抛出exception
        raise

try:
    result = process_data([])
    print(f"processing结果: {result}")
except ValueError as e:
    print(f" on 层捕获 to exception: {e}")

自定义exceptionclass

我们可以throughinheritanceExceptionclass or 其子class来creation自定义exceptionclass. 自定义exceptionclass通常用于表示specific于application程序 errorcircumstances.

# 自定义exceptionclass
class InvalidAgeError(Exception):
    """年龄无效exception"""
    def __init__(self, age, message="年龄无效"):
        self.age = age
        self.message = message
        super().__init__(self.message)
    
    def __str__(self):
        return f"{self.message}: {self.age}"

class NegativeAgeError(InvalidAgeError):
    """年龄 for 负exception"""
    def __init__(self, age):
        super().__init__(age, "年龄不能 for 负数")

# using自定义exception
def register_user(name, age):
    if age < 0:
        raise NegativeAgeError(age)
    elif age < 18:
        raise InvalidAgeError(age, "年龄必须满18岁")
    print(f"user {name} register成功!")

try:
    register_user("Alice", 25)
except InvalidAgeError as e:
    print(f"register失败: {e}")

try:
    register_user("Bob", 15)
except InvalidAgeError as e:
    print(f"register失败: {e}")

try:
    register_user("Charlie", -5)
except InvalidAgeError as e:
    print(f"register失败: {e}")

exceptionprocessing best practices

实践case: user输入verification

creation一个user输入verificationfunction, usingexceptionprocessing来processing各种输入error.

class InputValidationError(Exception):
    """输入verificationexception"""
    pass

class EmptyInputError(InputValidationError):
    """空输入exception"""
    pass

class LengthError(InputValidationError):
    """ long 度errorexception"""
    pass

class FormatError(InputValidationError):
    """格式errorexception"""
    pass

def validate_username(username):
    """
    verificationuser名
    
    Args:
        username: user名
    
    Returns:
        bool: verification is 否成功
    
    Raises:
        EmptyInputError: such as果user名 for 空
        LengthError: such as果user名 long 度不符合要求
        FormatError: such as果user名格式不符合要求
    """
    if not username:
        raise EmptyInputError("user名不能 for 空")
    
    if len(username) < 3 or len(username) > 20:
        raise LengthError("user名 long 度必须 in 3-20个字符之间")
    
    if not username.isalnum():
        raise FormatError("user名只能package含字母 and number")
    
    return True

def validate_email(email):
    """
    verification邮箱
    
    Args:
        email: 邮箱地址
    
    Returns:
        bool: verification is 否成功
    
    Raises:
        EmptyInputError: such as果邮箱 for 空
        FormatError: such as果邮箱格式不符合要求
    """
    if not email:
        raise EmptyInputError("邮箱不能 for 空")
    
    if '@' not in email or '.' not in email:
        raise FormatError("邮箱格式不正确")
    
    return True

def validate_age(age):
    """
    verification年龄
    
    Args:
        age: 年龄
    
    Returns:
        bool: verification is 否成功
    
    Raises:
        EmptyInputError: such as果年龄 for 空
        FormatError: such as果年龄不 is number
        ValueErro: such as果年龄不 in  has 效范围 in 
    """
    if not age:
        raise EmptyInputError("年龄不能 for 空")
    
    try:
        age_int = int(age)
    except ValueError:
        raise FormatError("年龄必须 is number")
    
    if age_int < 0 or age_int > 150:
        raise ValueError("年龄必须 in 0-150之间")
    
    return True

def register_user():
    """registeruser"""
    print("=== userregister ===")
    
    while True:
        try:
            username = input("请输入user名: ")
            validate_username(username)
            break
        except InputValidationError as e:
            print(f"error: {e}")
    
    while True:
        try:
            email = input("请输入邮箱: ")
            validate_email(email)
            break
        except InputValidationError as e:
            print(f"error: {e}")
    
    while True:
        try:
            age = input("请输入年龄: ")
            validate_age(age)
            break
        except (InputValidationError, ValueError) as e:
            print(f"error: {e}")
    
    print("\nregister成功!")
    print(f"user名: {username}")
    print(f"邮箱: {email}")
    print(f"年龄: {age}")

# testuserregister
if __name__ == "__main__":
    register_user()

互动练习

练习1: exceptionprocessing练习

creation一个function, 接收两个numberserving asparameter, 返回它们 商. usingexceptionprocessing来processing可能 error, such as除零error and class型error.

def safe_divide(a, b):
    """
    security地计算两个数 商
    
    Args:
        a: 被除数
        b: 除数
    
    Returns:
        float: 商
    
    Raises:
        ValueError: such as果输入不 is number
        ZeroDivisionError: such as果除数 for 零
    """
    # implementation你 code
    pass

# testfunction
test_cases = [
    (10, 2),
    (5, 0),
    ("10", 2),
    (10, "2"),
    ("10", "2"),
]

for a, b in test_cases:
    try:
        result = safe_divide(a, b)
        print(f"{a} / {b} = {result}")
    except Exception as e:
        print(f"{a} / {b} error: {e}")

练习2: fileoperationexceptionprocessing

creation一个function, 读取file in 容并返回. usingexceptionprocessing来processing可能 fileoperationerror, such asfile未找 to error and permissionerror.

def read_file(file_path):
    """
    读取file in 容
    
    Args:
        file_path: filepath
    
    Returns:
        str: file in 容
    
    Raises:
        Exception: such as果file读取失败
    """
    # implementation你 code
    pass

# testfunction
test_files = [
    "example.txt",
    "nonexistent_file.txt",
]

for file_path in test_files:
    try:
        content = read_file(file_path)
        print(f"file '{file_path}' 读取成功:")
        print(content)
    except Exception as e:
        print(f"file '{file_path}' 读取失败: {e}")

练习3: 自定义exceptionclass

creation一个银行accountclass, using自定义exceptionclass来processing各种accountoperationerror, such as余额不足, 无效金额etc..

# creation自定义exceptionclass
class BankAccountError(Exception):
    """银行accountexception"""
    pass

class InsufficientFundsError(BankAccountError):
    """余额不足exception"""
    pass

class InvalidAmountError(BankAccountError):
    """无效金额exception"""
    pass

class BankAccount:
    """银行accountclass"""
    
    def __init__(self, balance=0):
        self.balance = balance
    
    def deposit(self, amount):
        """
        存款
        
        Args:
            amount: 存款金额
        
        Raises:
            InvalidAmountError: such as果金额无效
        """
        # implementation你 code
        pass
    
    def withdraw(self, amount):
        """
        取款
        
        Args:
            amount: 取款金额
        
        Raises:
            InvalidAmountError: such as果金额无效
            InsufficientFundsError: such as果余额不足
        """
        # implementation你 code
        pass
    
    def get_balance(self):
        """
        获取余额
        
        Returns:
            float: account余额
        """
        return self.balance

# test银行account
account = BankAccount(1000)
print(f"初始余额: {account.get_balance()}")

try:
    account.deposit(500)
    print(f"存款 after 余额: {account.get_balance()}")
except BankAccountError as e:
    print(f"存款error: {e}")

try:
    account.withdraw(200)
    print(f"取款 after 余额: {account.get_balance()}")
except BankAccountError as e:
    print(f"取款error: {e}")

try:
    account.withdraw(2000)
    print(f"取款 after 余额: {account.get_balance()}")
except BankAccountError as e:
    print(f"取款error: {e}")

try:
    account.deposit(-100)
    print(f"存款 after 余额: {account.get_balance()}")
except BankAccountError as e:
    print(f"存款error: {e}")