Python Note -- Day 16. 异常处理 - 模块和包

21 异常处理

21.1 异常的含义和处理

21.1.1 什么是异常

非正常,没有达到预期的目标。

异常是一个事件,异常事件在程序运行过程中出现,会影响程序的正常执行。

异常分两种:
1.语法错误导致的异常
2.逻辑错误导致的异常

在程序无法正常运行处理时,会出现一个异常,在python中异常是一个对象,表示一个错误。

标准异常类 表格:https://www.runoob.com/python/python-exceptions.html

21.1.2 如何处理异常

1.如果错误发生的情况是可以预知的,那么就可以使用流程控制进行预防处理
比如:两个数字的运算,其中一个不是数字,运算就会出错,这时可以去判断来预防

n2 = '3'
if isinstance(n2,int):
    res = 10 + n2
    print(res)

2.如果错误发生的条件不可预知,可以使用 try:... except...在错误发生时进行处理
语法:

try:
    可能发生异常错误的代码
except:
    如果发生异常则进入 except 代码块进行处理

例子:假设读取的文件不存在,会发生错误,可以使用两种方式进行处理

  • 可以在文件读取前先判断当前的文件是否存在
  • 使用 try:... except...在错误发生时进行处理
try:
    with open('user.txt','r') as fp:
        res = fp.read()
        print(res)
except:
    print('wrong code')
print('continue processing ')

21.2 try:except 用法详解

21.2.1 处理指定的异常类

若引发了非指定的异常,则无法处理

try:
    s = 'hello'
    int(s)   # 引发ValueError
except ValueError as e:
# except IndexError as e:   # 非指定异常
    print(e,type(e))

 * 一个 try 语句可能包含多个except子句,分别来处理不同的特定的异常。最多只有一个分支会被执行。
* 处理程序将只针对对应的 try 子句中的异常进行处理,而不是其他的 try 的处理程序中的异常。
* 一个except子句可以同时处理多个异常,这些异常将被放在一个括号里成为一个元组,例如:

except (RuntimeError, TypeError, NameError):
    pass

21.2.2 多分支处理 异常类

不同的异常走向不同的处理

s = 'hello'
try:
    int(s)   # 引发ValueError
    # s[9]   # IndexError
except ValueError as e:
    print('valueerror',e)
except KeyError as e:
    print('keyerror',e)
except IndexError as e:
    print('indexerror',e)

21.2.3 通用异常类 Exception

s = 'hello'
try:
    int(s) 
except IndexError as e:
    print('indexerror',e)
except Exception as e:
    print('exceptionerror',e)

21.2.4 多分支异常+通用异常类

引发异常后,按照从上往下的顺序去执行对应的异常处理类

s = 'hello'
try:
    int(s)   
except ValueError as e:
    print('valueerror',e)
except KeyError as e:
    print('keyerror',e)
except IndexError as e:
    print('indexerror',e)
except Exception as e:
    print('exceptionerror',e)

21.2.5 try... except... else...

异常时执行except,没异常时执行else

s = 'hello'
try:
    int(s)
except ValueError as e:
    print('valueerror',e)
except KeyError as e:
    print('keyerror',e)
except IndexError as e:
    print('indexerror',e)
except Exception as e:
    print('exceptionerror',e)
else:
    print('try代码块中没有引发异常时,执行')

21.2.6 try... except... else...finally

finally无论是否引发异常,都会执行,通常用于一些清理工作

s = 'hello'
try:
    int(s)
    print('若前面引发异常,这个代码块不再执行')
except ValueError as e:
    print('valueerror',e)
except KeyError as e:
    print('keyerror',e)
except IndexError as e:
    print('indexerror',e)
except Exception as e:
    print('exceptionerror',e)
else:
    print('try代码块中没有引发异常时,执行')
finally:
    print('无论是否引发异常,都会执行这个代码块')

print('若上面有异常并进行了处理,后面的代码将继续执行')

21.2.7 使用 raise 语句,主动触发(抛出)异常

raise [Exception [, args [, traceback]]]
语句中 Exception 是异常的类型(例如,NameError)参数标准异常中任一种,args 是自己提供的异常参数。
最后一个参数是可选的(在实践中很少使用),如果存在,是跟踪异常对象。

try:
    raise Exception('wrong wrong')
except Exception as e:
    print(e)
def mye( level ):
    if level < 1: # 符合某种条件,产生异常
        raise Exception,"Invalid level!"
        # 触发异常后,后面的代码就不会再执行
try:
    mye(0)            # 触发异常
except Exception,err:
    print 1,err
else:
    print 2
a = int(input('please enter number '))
try:
    if a < 30:
        raise Exception('wrong variable set',a)
except Exception as e:
    print(e) # ('wrong variable set', 2)
else:
    print('correct')
finally:
    print('move to next part')

最后一个except子句可以忽略异常的名称,它将被当作通配符使用。你可以使用这种方法打印一个错误信息,然后再次把异常抛出。 

import sys

try:
    f = open('myfile.txt')
    s = f.readline()
    i = int(s.strip())
except OSError as err:
    print("OS error: {0}".format(err))
except ValueError:
    print("Could not convert data to an integer.")
except:
    print("Unexpected error:", sys.exc_info()[0])
    raise
try:
    runoob()
except AssertionError as error:
    print(error)
else:
    try:
        with open('file.log') as file:
            read_data = file.read()
    except FileNotFoundError as fnf_error:
        print(fnf_error)
finally:
    print('这句话,无论异常是否发生都会执行。')

21.2.8 assert 断言

直接判断语句是否成立

断言可以在条件不满足程序运行的情况下直接返回错误,而不必等待程序运行后出现崩溃的情况

assert 1 == 1  # 若成立,则执行后面语句
assert 2 == 1  # 不成立,则报错
import sys
assert ('linux' in sys.platform), "该代码只能在 Linux 下执行"

21.3 自定义异常处理类

当异常出现时,对异常信息进行处理 并写入日志
日志的基本格式:
日期时间, 异常的级别
异常信息:引发的异常类,异常的信息,文件及行号

import traceback  回溯模块 https://docs.python.org/3/library/traceback.html
import logging    日志模块 https://docs.python.org/3/library/logging.html

# try:
#     int('aa')
# except:
#     # 通过 traceback 模块获取异常信息
#     errmsg = traceback.format_exc()
#     print(errmsg,repr(errmsg))
# 自定义异常日志处理类
class Myexception():
    def __init__(self):
        import traceback
        import logging

        # logging 的基本配置
        logging.basicConfig(
            filename='error.log',   # 日志存放的文件及目录
            format='%(asctime)s %(levelname)s \n %(message)s ',  # 格式化存储的日志格式
            datefmt='%Y-%m-%d %H:%M:%S'
        )

        # 写入日志
        logging.error(traceback.format_exc())

# 使用自定义异常处理类
try:
    int('aa')
except:
    print('在此处进行异常处理')
    Myexception()  # 在异常处理的代码块中 调用自定义异常类

print('hmmm...')

22 模块与包

模块

定义的一个python文件,后缀名为.py,这个文件被称为模块
模块中通常会定义一些相似的类,函数等代码的内容,提供给别的程序 引入后使用

系统模块

即一个python程序脚本,专门提供给程序员自己使用,是在安装好python环境时就已存在,需要的时候可以使用import导入到程序中使用
import logging,json,time...

自定义模块

自己创建一个python脚本,定义一些类或方法,供别的脚本导入后使用

22.1 自定义模块的使用

在当前脚本中如果需要使用一些已经定义好的功能时,可以选择对应的模块

  • 自定义模块中,通常只是去定义类或函数,变量,等,并不调用
  • 若在自定义模块中,想要写一些测试代码,在当前模块作为主程序使用时执行, 作为模块被别的程序导入时,不执行;可以把测试代码写到下面代码块中:
if __name__ == '__main__':
    print('这个位置写的代码只有当前脚本被直接运行时触发')

特殊的变量 __name__
__name__这个变量,在当前脚本作为模块被别的程序导入时,它的值是当前这个模块的名称
在当前脚本作为主程序执行,它的值为__main__

# 使用自定义异常处理模块
import Myex

# 使用模块中定义的类
obj = Myex.Myexception()
print(obj)

# 使用模块中的函数
Myex.func()

# 使用模块中的变量
res = Myex.vari
print(res)
print(Myex.__name__)

# 想使用模块中的内容,除了导入模块,还可以在指定模块中导入指定的内容
from Myex import vari  # 导入Myex模块中 vari 变量
from Myex import vari as one   # 导入变量,并起别名
print(vari)
print(one)

22.2 自定义包的使用

可以理解为一个文件夹,包含多个python文件

包的结构

包(文件夹)
|----__init__.py   # 包的标志性文件(可有可无)
|----a.py          # a模块(文件)
|----b.py          # b模块(文件)
|----...
|----包(文件夹中的文件夹)
    |----__init__.py   
    |----c.py          
    |----d.py

导入方式

绝对导入

# 0. 如果需要使用包,可以直接导入,不推荐
# 直接把包当作模块导入,可以用的内容是__init__.py文件中定义的
import pp
pp.funcpp()

# 1. 可以导入模块中的所有内容,
# 注意:这个内容是由 __init__.py 文件中定义的
# __all__ = ['filename','']变量指定的
from pp import  *
aa.func()

# 2. 导入指定包中的指定模块
from pp import aa,bb
aa.func()
bb.funcc()

# 3. 从指定包中的指定模块 导入指定的内容
from pp.bb import funcc
funcc()

# 4. 从指定包的子包中 导入模块
from pp.ppy import aaa
aaa.func()

# 5. 从指定包的子包的指定模块中 导入指定的内容
from pp.ppy.bbb import funcc
funcc()

22.3 导入方式的分类

22.3.1 绝对导入

使用专门的 [搜索路径] 去查找和导入指定的包或模块

import 模块
import 包
import 包.模块
from 模块 import 内容
from 包 import 模块
from 包.模块 import 内容

22.3.2 相对导入

注意:相对导入只能在非主程序的模块(不需要直接运行的模块文件)中使用,
不要直接运行相对导入的模块的文件

from .包名/模块名 import 模块/内容
from ..包名/模块名 import 模块/内容
. 代表当前, .. 代表上一级

# 假设在当前(子包中的模块文件(pp/ppy/aaa.py))中需要当前包的另一模块 bbb.py
from .bbb import funcbbb
funcbbb()

# from . import bbb
# bbb.funcbbb()

# 在另外一个主运行程序导入方才的子包模块
from pp.ppy import aaa
# 能立即运行刚才的代码

# 假设在当前(子包中的模块文件(pp/ppy/aaa.py))中需要
# 上一级包的另一模块 bbb.py
from ..aa import func
func()
# 在另外一个主运行程序导入方才的子包模块
from pp.ppy import aaa
# 能立即运行刚才的代码
  • 了解 搜索路径
    导入模块或包时,程序查找的路径
    主要搜索路径:
    1.当前导入模块的程序所在的文件
    2.python的扩展目录中 ../Python3/lib
    3.python解释器指定的 第三方模块位置 /lib/sitepackages
# 在当前脚本中 查看 包或模块的 搜索路径
import sys
print(sys.path)
# ['E:\\PycharmProjects\\pythonProject', 'E:\\PycharmProjects\\pythonProject', 'E:\\Programs\\Python\\Python37\\python37.zip',
# 'E:\\Programs\\Python\\Python37\\DLLs', 'E:\\Programs\\Python\\Python37\\lib',
# 'E:\\Programs\\Python\\Python37', 'E:\\Programs\\Python\\Python37\\lib\\site-packages']

# 可以自己定义路径,加入到搜索路径中
sys.path.append('D:/one')

22.4 单入口程序

指整个程序都是经过一个主程序文件运行,其它程序都封装成了包或模块

单入口文件是作为程序直接被运行的唯一文件,其他都是作为模块或包,被导入单入口中去执行

ATM/  
|--- main.py    # 当前程序的主入口文件,单入口文件  
|--- package/   # 主要程序模块包  
|--- |---__init__.py   # 包的初始化文件  
|--- |---View.py       # 视图函数模块  
|--- |---Controller.py # 控制器模块  
|--- |---Card.py       # 银行卡模块  
|--- |---User.py       # 用户模块  
|--- databases/ # 数据存储文件夹  
|--- |--- user.txt  
|--- |--- user_id_card.txt

main 是程序的主入口,会被直接作为主程序运行,main.py 文件中必须使用 绝对导入方式

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值