Python3学习笔记_异常处理_20200509/0512
19、异常处理
#异常是程序出现了意想不到的情况
#有异常出现,要不要去解决?要
#如果异常不解决,程序会崩溃,停止运行,下面的代码没法运行
#异常捕获,捕获异常
#如果出现异常,我们会让他按照事先规定的规则去执行对应的操作,记录错误日志,log
try 要运行的有可能发生异常的代码:
代码
except 异常:
出现异常的时候要运行的代码(执行的操作),记录日志
#一旦try当中出现异常,立即跳到except子句,try剩下的代码不会再执行
#示例1:
lst=['yuz']
print(lst[3])
#示例2:解决示例1中异常情况
lst=['yuz'] #不会出现异常
try:
#有可能出现异常的代码
#下面的代码会执行,不然怎么知道是异常呢
print(lst[3]) #有可能出现异常
print('try...')
#一旦try当中的代码报错,立即跳到except
#try报错代码的下面将不会继续执行
except:
#如果出现异常,会执行except分支的代码
print('记录错误日志')
print('hengheng')
print('hahahaha')
#try…except 的进阶用法:
#最基础的异常捕获
lst=['yuz']
try:
print(lst[3])
except:
print('错误日志')
#知道哪行代码需要加异常处理,知道什么代码需要放到try里面
a=4
b=1
print(a*b) #需不需要加异常处理?
a='a'
b='b'
print(a*b) #如果事先不知道传入的是什么类型,则需要加异常处理
try:
print(a*b)
except:
print('参数错误,记录日志')
总结:异常是好事还是坏事?好事
#①
lst=['yuz']
print(lst[3]) #报错了,说明是好事,知道哪里出错了
#②
lst=['yuz']
try:
print(lst[3])
except:
pass
print('hello') #写的异常捕获不怎么高明,没有报错,不知道哪里有问题,自欺欺人
#③
a=4
b=1
print(a/b) #这里要不要加try...except?要加,因为a,b是变量,万一b=0呢,所以要加
#④
a=4
b=0
lst=['yuz']
print(a/b)
print(lst[3])
捕获异常:
a=4
b=0
lst=['yuz']
try:
print(a/b)
print(lst[3])
except:
print('程序出现错误') #捕获异常,到底出现了什么问题知不知道?不知道,这样的话,要引入下面的一个条件
a=4
b=0
lst=['yuz']
try:
print(a/b)
print(lst[3])
except Exception as e: #将捕获的异常赋值给 e 变量
print('程序出现错误 {}'.format(e)) #这样会把错误类型打印出来
a=4
b=0
lst=['yuz']
try:
print(lst[3])
print(a/b)
except Exception as e:
print('程序出现错误 {}'.format(e))
#try里面的语句调换顺序,报的错误就会不一样,
#同一个try不可能捕获两个异常的,如果遇到一个异常就直接执行except语句了
#如果想把两个错误都给收集起来,那就写下面的两个try
try:
print(lst[3])
except Exception as e:
print('程序出现错误 {}'.format(e))
try:
print(a/b)
except Exception as e:
print('程序出现错误 {}'.format(e)) #这样就可以捕获两个异常
#异常捕获的进阶版:
指明出现的异常类型
先不要加异常,让他报错(开发主动试错)
lst=['yuz']
print(lst[3]) #报错:IndexError
lst=['yuz']
try:
lst[3]
except IndexError as e:
print('出现异常:{}'.format(e))
lst=['yuz']
try:
print(4/0) #这个异常是捕获不到的,那如何解决呢?
lst[3]
except IndexError as e:
print('出现异常:{}'.format(e))
lst=['yuz']
try:
print(4/0)
lst[3]
except IndexError as e:
print('出现异常:{}'.format(e))
except ZeroDivisionError as e:
print('出现除法错误:{}'.format(e)) #这样就会把所有的异常分开捕获
lst=['yuz']
try:
print(4/0)
lst[3]
except IndexError as e:
print('出现异常:{}'.format(e))
except ZeroDivisionError as e:
print('出现除法错误:{}'.format(e))
finally:
#不管有没有报错,finally都会执行的
print('hello world')
#raise:手动抛出异常,让程序报错
def join_girl_team(age,gender):
if age>22:
raise ValueError('age must be 小于22')
print('可以加入女子足球队')
join_girl_team(23,'女')
#错误类型
常见的异常
ImportError:无法引入模块或包
IndexError:下标索引超出序列边界
NameError:使用一个还未赋予对象的变量
SynataxError:代码逻辑语法出错,不能执行,不能去捕获
TypeError:传入的对象类型与要求不符
ValueError:传入一个不被期望的值,即使类型正确
KeyError:试图访问你字典里不存在的键
IOError:输入输出异常,文件操作
try:
fasjdlf #语法错误是没有办法去捕获的
except:
print('hello world')
#finally示例
try:
f=open('demo.txt','r') #打开文件报错的时候
f.read()
except:
pass
finally:
f.close() #不管怎样都要尝试关闭文件
#以上finally示例,相当于with open()
#可不可以把异常分组?可以
#分组有什么好处?
发现了一个严重级别,阻塞级别的bug(短信通知相关人员赶紧集合的代码),一个轻微级别的bug(记录日志的代码)
针对不同的组进行不同的操作
try:
1/0
['yuz'][3]
{'name':'lemon'}['age']
except (IndexError,KeyError) as e:
print('可以同时捕获IndexError 和 KeyError')
except ZeroDivisionError as e:
print('除数不能为0')
try:
1/0
['yuz'][3]
{'name':'lemon'}['age']
except IndexError as e:
print('可以捕获IndexError ')
except KeyError as e: #如果说IndexError和KeyError是相同级别的bug,异常的时候执行的代码一样,如果不分组,要重复的写代码,分组后就不需要了
print('可以捕获KeyError')
except ZeroDivisionError as e:
print('除数不能为0')
try:
1/0
['yuz'][3]
{'name':'lemon'}['age']
except IndexError as e:
print('可以捕获IndexError ')
except KeyError as e:
print('可以捕获KeyError')
except ZeroDivisionError as e:
print('除数不能为0')
except Exception as e: #尽量少用Exception,因为使用这个不知道是什么类型的错误,不好定位问题,这样是不负责任的
print('其他错误类型')
20、模块和包
什么是模块?
.py文件就是一个模块 【实际上,.pyc, .pyo, .pyd, so, dll】—动态库
什么是包?
以包含了__init__.py的模块的文件夹(目录)
模块和包有什么作用?
就是为了组织代码的,方便管理代码
模块的导入:
使用之前已经定义好的代码
使用其他模块里面的函数、变量、类,就叫模块导入
import ...
import 路径.路径.模块名----》路径从哪里开始?从你的项目根目录的下面开始
import 路径.包名---------》路径从哪里开始?从你的项目根目录的下面开始
#示例1:
import lemonban.Lemon_lianxi.demo
#使用:
lemonban.Lemon_lianxi.demo.visit
#示例2:
import lemonban.Lemon_lianxi
from ... import ... #可以简化其他模块的调用
#示例1:
from lemonban.Lemon_lianxi import demo
demo.visit()
#示例2:
from lemonban.Lemon_lianxi.demo import visit
visit()
#示例3:
from lemonban.Lemon_lianxi.demo import visit,response
visit()
response()
模块分类:
内置模块:Python自带的,一般使用:import …(比如:import os)
第三方模块:别人写好的模块,需要安装,pip install requests,import…/from … import …
自定义模块:自己写的模块,通常放在包里面,from 包 import 模块
扩展内容:
#1:
from ... import * ------>表示从模块中导入所有的代码
#示例:
from lemonban.Lemon_lianxi.demo import * #一般不要使用,可能会出现和这个模块里的函数重名
#2:
from ... import sth as other ------>as 重命名,取别名,就是为了避免重复
#示例:
from lemonban.Lemon_lianxi.demo import visit as visit_new
打印导入的模块路径:
import sys
print(sys.path)
name ----------->表示的是当前文件的模块名
----------->运行文件,脚本,是个模块,是个特殊的模块
----------->我们是通过这个文件运行程序的
----------->通过模块导入形式运行的,__name__就是文件名、模块名
----------->直接运行的文件/脚本,__name__就不是文件名、模块名,是固定的:main
#示例1:
from lemonban.Lemon_lianxi import demo #这个模块中也有代码print(__name__),但是在这个文件中执行导入的这个模块,结果为:lemonban.Lemon_lianxi.demo
print(__name__) #结果是:__main__
#示例2
demo.py
if __name__=='__mian__':
print('demo')
demo1.py
if __name__=='__mian__':
print('demo1')
demo2.py
if __name__=='__mian__':
print('demo2')
在demo3.py里运行:
from lemonban.Lemon_lianxi import demo
from lemonban.Lemon_lianxi import demo1
from lemonban.Lemon_lianxi import demo2
if __name__=='__mian__':
print('demo3') #运行后的结果为:demo3
#示例3:
demo.py
print('demo')
demo1.py
print('demo1')
demo2.py
print('demo2')
在demo3.py里运行:
from lemonban.Lemon_lianxi import demo
from lemonban.Lemon_lianxi import demo1
from lemonban.Lemon_lianxi import demo2
print('demo3') #结果为:demo demo1 demo2 demo3
if name==‘mian’:
#可以写测试代码,因为如果该模块是通过导入的形式运行,则这个代码就不会执行,只有在本文件中才会执行
问题1:import 模块.函数 这样写可以吗?
如:import lemonban.Lemon_lianxi.demo.visit
这样写是不可以的
导入模块,查找模块的顺序:项目目录–》Python安装目录(lib)----》pip install 第三方模块(site-package)
导入内置和第三方模块,直接import sth 即可,不需要写路径
导入自定义模块,通常是从根目录的下面开始找的,需要写明路径
为了不写路径,可以把自定义模块放到Python安装目录的lib下或者是第三方模块的site-package下,这样可以直接导入模块了
os模块:
#第一种方式:
import os.path
#第二种方式:
from os import path
#os.path主要处理系统路径相关的操作
如何获取文件的绝对路径?
print(os.path.abspath(file))
什么是绝对路径?从系统的盘符或者是系统根目录开始
什么是相对路径?一个路径相对于另一个路径的说法
file-----当前文件的相对路径
name-----模块名,没有路径
print(__file__)
print(__name__)
#用的最多的是os.path.abspath(file),因为绝对路径不会变,相对路径会发生变化
1》获取现在的文件绝对路径:
file_path=os.path.abspath(__file__)
路径拼接 文件/文件
os.path.join(file_path,'demo.txt')
#得到的结果:..lemonban/day1-0414/北京_Lemon_29期_0414_python基础.py/demo.txt
#实际上是不存在这种情况的,因为文件下面不能是文件,所以我们应该获取当前文件的上级目录,然后再拼接文件,就得到这个文件的
2》获取上一级路径:
dir_path=os.path.dirname(file_path)
3》路径拼接 文件夹/文件
print(os.path.join(dir_path,'demo.txt')) #得到的结果是:..lemonban/day1-0414/demo.txt
总结:所有获取到的路径,只是一个路径的表示,并不代表这个文件或者路径真的存在,
得到的路径是一个字符串,这个字符串是一个路径格式
如果想真的要创建一个文件,可以用open函数操作
with open('demo.txt','w') as f:
f.write('要添加的内容')
#获取当前的工作目录
print(os.getcwd())
#创建一个新的目录(文件夹)
print(os.mkdir('new_dictory')) #第二次运行就会报错,因为该文件已经存在了
#判断一个路径存不存在
print(os.path.exists('/Users/qinningmeng/PycharmProjects/test_auto/lemonban/day1-0414/demo.txt'))
#所以创建路径的时候,可以先判断是否存在,再添加
if not os.path.exists('new_dictory'): #可以传相对路径,也可以传绝对路径
os.mkdir('new_dictory')
#判断路径是否是一个文件
print(os.path.isfile(os.getcwd()))
#判断路径是否是一个文件夹
print(os.path.isdir(os.getcwd()))