上节回顾:

1、collections 模块    :基础数据类型的扩展

2、时间模块    :和时间相关的模块——三种格式时间戳、格式化字符串、结构化时间

3、random 模块    :生成随机数。从一个数据结构中随机抽取数据、打乱序列的顺序

4、os模块     :操作系统:文件与文件夹的创建和删除、路径相关的操作、执行系统命令

5、sys模块    :python解释器,sys.argv python文件的执行,sys.pathon 模块导入的

6、序列化模块  :序列化,将数据结构转换成字符串序列,jison、pickle、shelve

7、re模块    :和正则表达式相关的,正则表达式,是一种匹配字符串的规则

补充:

1、pickle模块提供了四个功能:dumps、dump(序列化、存)、load(反序列化、读)、load(不仅可以序列化字典、

              列表。。。可以把python中任意的数据类型序列化)

2、程序中难免出现错误,而错误分成两种:

  (1)语法错误(这种错误,根本过不了python解释器的语法检测,必须在程序执行前改正)

  (2)逻辑错误

3、什么是异常:

  异常就是程序运行时发生的错误信号,在python中,错误触发的异常如下(排除错误的方法:就是从下往上排除)

4、python中的异常种类

  在python中不同的异常可以用不同的类型(python中统一了类和类型,类型即类)去标识。不同的类对象标识不同的异常,一个异常标识一个错误

  1、触发IndexError

  2、触发KeError

  3、触发ValueError

 5、什么是异常处理

  python解释器检测到错误,触发异常(也允许程序员自己触发异常))

  程序员编写特定的代码,专门用来捕捉这个异常(这段代码与程序逻辑无关,与异常处理有关)

  如果捕捉成功则进入另外一个处理分支,执行你为其定制的逻辑,使程序不会崩溃,这就是异常处理

6、为什么要进行异常处理

  python解释器去执行程序,检测到了一个错误时,触发异常,异常出发后且没有被处理的情况下,程序就在当前异常处终止

  后面的代码就不会运行,谁会用一个运行着突然就崩溃的软件。

  所以你必须提供一种异常处理机制来增强你程序的健壮性和容错性

7、如何进行异常处理:

  首先须知,异常是由程序的错误引起的,语法上的错误跟异常处理无关,必须在程序运行前修正  

  (1)使用if判断式  (异常发生之前的处理) 

num1=input(">>>:")
if num1.isdigit():
    print(int(num1),type(int(num1)))
elif num1.isspace():
    print("1如果输入的是空格,就执行这里的逻辑")
elif len(num1)==0:
    print("2如果输入的是空,就执行这里的逻辑")
else:
    print("3如果是其他情况就执行这里")
'''
问题一:
使用if的方式我们只为第一段代码加上了异常处理,但这些if,跟你的代码逻辑并无关系,这样你的代码会因为可读性差而不容易被看懂

问题二:
这只是我们代码中的一个小逻辑,如果类似的逻辑多,那么每一次都需要判断这些内容,就会倒置我们的代码特别冗长。
'''
使用IF判断处理异常
def test():
    print("test running")
choice_dic={
    "1":test
}
while True:
    choice=input(">>>:").strip()
    if not choice or choice not in choice_dic: #这便是一种异常处理机制啊
        continue
    choice_dic[choice]()
其他处理异常的机制

8、python为每一种异常定制了一个类型,然后提供了一种特定的语法结构用来处理异常

(1)基本语法(异常发生之后的处理)

try:
     被检测的代码块
except 异常类型:
     try中一旦检测到异常,就执行这个位置的逻辑
try:
    f=open("函数作业",encoding="utf-8")
    g=(line.strip() for line in f)
    print(next(g))
    print(next(g))
    print(next(g))
except StopIteration:
    f.close()
'''
next(g)会触发迭代f,依次next(g)就可以读取文件的一行行内容,无论文件a.txt有多大,同一时刻内存中只有一行内容。
提示:g是基于文件句柄f而存在的,因而只能在next(g)抛出异常StopIteration后才可以执行f.close()
'''
处理异常的小例子

(2)异常只能用来处理指定的异常情况,如果非指定异常则无法处理

#未捕捉到异常,则直接报错
s1 = 'hello'
try:
    int(s1)
except IndexError as e:
    print(e)

(3)多分支处理

s1 = 'hello'
try:
    int(s1)
except IndexError as e:
    print("1:",e)
except KeyboardInterrupt as e:
    print("2",e)
except ValueError as e:
    print("3",e)
# 3 invalid literal for int() with base 10: 'hello'

(4)万能异常在python的异常中,有一个万能异常:Exception,他可以捕捉任意异常

s1 = 'hello'
try:
    int(s1)
except Exception as e:
    print("异常原因",e)
# 异常原因 invalid literal for int() with base 10: 'hello'

(5)异常的其他机构

s1 = '1'
try:
    int(s1)
except IndexError as e:
    print(1,e)
except KeyError as e:
    print(2,e)
except ValueError as e:
    print(3,e)
except Exception as e:
   print(4,e)
else:
    print('try内代码块没有异常则执行我')
finally:
    print('无论异常与否,都会执行该模块,通常是进行清理工作')
#try内代码块没有异常则执行我
#无论异常与否,都会执行该模块,通常是进行清理工作
多分支+exception

(6)主动触发异常  (raise+一个错误类型) 后面面向对象会讲到

try:
    raise  TypeError("类型错误")
except Exception as e:
    print(1,e)          #爆出异常内容,如果没有上面括号的内容则是空白
    # 1类型错误

(7)自定义异常(写框架,学面向对象的时候会用到)

class EvaException(BaseException):
    def __init__(self,msg):
        self.msg=msg
    def __str__(self):
        return self.msg
try:
    raise EvaException("类型错误")
except EvaException as e :
    print(1,e)
#1 类型错误

(8)断言(assert+ 条件)

(9)try ...except 比较 if方式有什么好处  

  try ...excep这种异常处理机制就是取代if 那种方式,让你的程序在不牺牲可读性的前提下增强健壮性和容错性

  异常处理中为每一个异常定制了异常类型(Python中统一了类与类型,类型即类),对于同一种异常,一个except就可以捕捉到

  可以同时处理多段代码的异常(无需写多个if判断式)减少了代码,增强了可读性

使用try...except 的方式

1:把错误处理和真正的工作分开来

2:代码更容易组织,更清晰,复杂的工作任务更容易实现;

3:毫无疑问,更安全了,不至于由于一些小的疏忽而使程序意外崩溃了

最常用的:try……except 

     finally

什么时候用异常处理

有的同学会这么想,学完了异常处理后,好强大,我要为我的每一段程序都加上try...except,干毛线去思考它会不会有逻辑错误啊,这样就很好啊,多省脑细胞===》2B青年欢乐多

try...except应该尽量少用,因为它本身就是你附加给你的程序的一种异常处理的逻辑,与你的主要的工作是没有关系的
这种东西加的多了,会导致你的代码可读性变差,只有在有些异常无法预知的情况下,才应该加上try...except,其他的逻辑错误应该尽量修正

 一、模块:

1、什么是模块?

  常见的场景:一个模块就是一个包含了python定义和声明的文件,文件名就是让模块名字加上。py的后缀

  但其实impo加载的模块氛围四个通用类别:

   (1)使用python编写的代码(.py文件)

  (2)已经被编译为共享库或DLL的c或c++扩展

  (3)包好一组模块的包

  (4)使用c编写并链接到python解释的内置模块

2、为什么要使用模块

3、定义模块,调用函数,查看变量

import my_module    #小司机
# 1、先查看自己的内存里有没有
#     有就不干活,没有再倒进来
# 2、创建一个命名空间,在这个命名空间中执行代码
# 3、创建了一个my_module这个名字,给命名空间中变量和my_module绑定在一起
def drive():
    print("数学老师的车")
price="不要钱"
my_module.drive()   #快上车
print(my_module.price)  #一个人20
drive()     #数学老师的车
print(price)    #不要钱
模块的建立和使用

4、开发的六大原则之二:不能相互引用

二、import...as

1、给模块起别名:一个变量的名字只能指向一个内存地址

2、数据库中会用到重命名,写的代码能够兼容两个不同的数据库

例子:

(1)有两中sql模块mysql和oracle,根据用户的输入,选择不同的sql功能

# mysql.py
def sqlparse():
    print("from mysql sqlparse")
# oracle.py
def sqlparse():
    print("from oracle sqlparese")
# test.py
db_type=input(">>>:")
if db_type=="mysql":
    import mysql as db
elif db_type=="oracle":
    import oracle as db
db.sqlparse()
实例用法

(2)为已经导入的模块起别名的方式对编写可扩展的代码很有用,假设有两个模块xmlreader.py和csvreader.py,它们都定义了函数read_data(filename):用来从文件中读取一些数据,但采用不同的输入格式。可以编写代码来选择性地挑选读取模块,例如

if file_format == 'xml':
    import xmlreader as reader
elif file_format == 'csv':
    import csvreader as reader
data = reader.read_date(filename)
实例用法2

3、import多个模块

    (1)先导入内置模块

   (2)再导入扩展模块

   (3)最后导入自定义模块

三、from....import

1、

对比import my_module,会将源文件的名称空间'my_module'带到当前名称空间中,使用时必须是my_module.名字的方式

而from 语句相当于import,也会创建新的名称空间,但是将my_module中的名字直接导入到当前的名称空间中,在当前名称空间中,直接使用名字就可以了、

这样在当前位置直接使用read1和read2就好了,执行时,仍然以my_module.py文件全局名称空间

#测试一:导入的函数read1,执行时仍然回到my_module.py中寻找全局变量money
#demo.py
from my_module import read1
money=1000
read1()
'''
执行结果:
from the my_module.py
spam->read1->money 1000
'''

#测试二:导入的函数read2,执行时需要调用read1(),仍然回到my_module.py中找read1()
#demo.py
from my_module import read2
def read1():
    print('==========')
read2()

'''
执行结果:
from the my_module.py
my_module->read2 calling read1
my_module->read1->money 1000
例子详细说明

2、

3、

4、三种使用方法

5、from...import*

  受到__all__的限制,如果不定义__all__就默认引入所有

 如果定义了,那么列表中有什么,就能引入什么

如果引入其他则会报错

 

 

6、测试使用:(不重要)

四、把模块当做脚本执行

 1、把模块当作脚本运行

def fib(n):   
    a, b = 0, 1
    while b < n:
        print(b, end=' ')
        a, b = b, a+b
    print()

if __name__ == "__main__":
    print(__name__)
    num = input('num :')
    fib(int(num))

2、执行python解释器,已经在内存中加载了一些内置的模块了

  导入模块的时候,如果模块不存在sys.modules,才从sys.path给的路径中依次去查找

  sys.path完全可以决定某个模块能不能被找到(除了已经在内存中加载一些内置的模块)

3、当py文件被当做一个模块导入的时候,会自动生成一个pyc文件

  pyc文件是这个代码编译之后的文件,节省了每一次导入代码之后还要编译的时间

      pyc是存在硬盘上的和内存没有关系

4、查看内置的所有方法:

import my_module
print(dir(my_module))

5、软件开发规范

#=============>bin目录:存放执行脚本
#=============>conf目录:存放配置文件
#=============>core目录:存放核心逻辑
#=============>db目录:存放数据库文件
#=============>lib目录:存放自定义的模块与包
#=============>log目录:存放日志