Python学习笔记九(异常、模块)

异常

什么是异常

程序发生错误,既程序非正常终止,则为异常。异常会让程序终止,这样的程序很不友好,我们希望程序异常结束时能给出提示。


1/0

# 结果为:
# Traceback (most recent call last):
#   File "E:/workspace/pycharm/pycharm/Demo.py", line 1, in <module>
#     1/0
# ZeroDivisionError: division by zero


捕获异常

try ... except ... 用于捕获异常,处理异常,程序在一次运行中只会产生一个异常。

格式


try:
    pass
except:
    pass


一个try 可以配合多个except 使用,每一个except 认为是一个分支。


try:
    1 / 0
except:
    print("发生异常程序,即将退出")

# 结果为:
# 发生异常程序,即将退出


捕获异常,作出提示,程序的友好性有所提升。

捕获异常的方式
  • 单分支捕获指定异常
  • 单分支捕获指定多个异常
  • 多分支捕获异常
  • 单分支捕获常见异常

捕获指定异常

捕获指定异常(一个分支捕获一个异常)


try:
    1 / 0
except ZeroDivisionError:
    print("被除数不能为 0")

# 结果为:
# 被除数不能为 0

如果需要获得异常的一些信息怎么办?使用 as 为异常对象起一个别名


try:
    1 / 0
except ZeroDivisionError as exc:
    print("被除数不能为 0 ,"
          "异常信息:%s ,"
          "异常代码所在的行数:%d" % (exc, exc.__traceback__.tb_lineno))

# 结果为:
# 被除数不能为 0 ,异常信息:division by zero ,异常代码所在的行数:2


单分支指定捕获多个异常

当多个异常处理逻辑相同时,可以放在一个分支中进行处理。


try:
    # max()  # TypeError
    # max([])  # ValueError
    pass
except (TypeError, ValueError) as exc:
    print("异常信息:%s ,"
          "异常代码的行数:%d" % (exc, exc.__traceback__.tb_lineno))


通过元组的形式可以在一个分支指定捕获多个异常,但是每次只有一个异常被捕获处理,为啥?因为一次只会产生一个异常。

多分支捕获异常


try:
    max()  # TypeError
    # max([])  # ValueError

except ValueError as exc:
    print("异常信息:%s ,"
          "异常代码的行数:%d" % (exc, exc.__traceback__.tb_lineno))
except TypeError as exc:
    print("异常信息:%s ,"
          "异常代码的行数:%d" % (exc, exc.__traceback__.tb_lineno))


单分支捕获常见异常


try:
    max()  # TypeError
    # max([])  # ValueError

except Exception as exc:  # 单分支捕获常见异常
    print("异常信息:%s ,"
          "异常代码的行数:%d" % (exc, exc.__traceback__.tb_lineno))


# Exception 的直接子类
# ArithmeticError(Exception)
# AssertionError(Exception)
# AttributeError(Exception)
# WindowsError(Exception)
# BufferError(Exception)
# Warning(Exception)
# EOFError(Exception)
# ImportError(Exception)
# SyntaxError(Exception)
# LookupError(Exception)
# MemoryError(Exception)
# NameError(Exception)
# RuntimeError(Exception)
# ReferenceError(Exception)
# StopAsyncIteration(Exception)
# StopIteration(Exception)
# SystemError(Exception)
# TypeError(Exception)
# ValueError(Exception)
# 19 个


异常的传递

def func1():
    1 / 0

def func2():
    func1()

def func3():
    func2()

func3()

# 结果为:
# Traceback (most recent call last):
#   File "E:/workspace/pycharm/pycharm/Demo.py", line 10, in <module>
#     func3()
#   File "E:/workspace/pycharm/pycharm/Demo.py", line 8, in func3
#     func2()
#   File "E:/workspace/pycharm/pycharm/Demo.py", line 5, in func2
#     func1()
#   File "E:/workspace/pycharm/pycharm/Demo.py", line 2, in func1
#     1 / 0
# ZeroDivisionError: division by zero



异常的传递

通过错误日志可以看出来在第十行调用了func3 ,func3 调用了 func2 ,func2 调用了func1 ,在行2 也就是func1 里面出错,没有处理错误,错误向上传递到func2 ,再传给func3 ,直到func3 的调用处都没有处理异常,程序异常终止。

自定义异常


class UserDefinedException(Exception):  # 继承Exception类
    '''自定义的异常类'''

    def __init__(self):
        pass

raise UserDefinedException()  # 使用raise 抛出一个UserDefinedException 异常



模块

什么是模块

一个 .py 文件就是一个模块,作用:分工,一个人负责某几个模块。

模块的导入

什么是模块名

前面已经说了一个 .py 文件就是一个模块,所以模块名就是 .py 文件的文件名。文件名将会用于标识符,所以文件名必须满足标识符的命名规则,否则不能导入。

导入

  • import 模块名
  • form 模块名 import 功能

模块 piece.py 的内容


def func():
    print("------ piece func -----------")


使用import 导入


import piece  # impotent 模块名,直接找人帮忙

piece.func()  # 模块名.功能名 使用,功能包括模块中的方法、变量、类等都可以使用。

# 结果为:
# ------ piece func -----------



# as 定义别名,结合import 使用 
import piece as p  # 使用as 给模块名 定义别名

p.func()  # 别名.功能名

# 结果为:
# ------ piece func -----------
  
  

import 导入可以理解为交了一个朋友(导入模块),比如说你的朋友会做做菜(模块中的功能),如果你需要做菜(想使用模块中的功能),你得先找到你的朋友(通过模块名),然后让他帮你做菜(调用功能)

form 模块名 import 功能


from piece import func  # form 模块名 import 功能,只能导入指定的功能

func()  # 直接使用

# 结果为:
# ------ piece func -----------
  


# as 结合 form import 使用

# form 模块名 import 功能 as 别名,功能包括模块中的方法、变量、类等都可以使用。
from piece import func as f 

f()  # 直接使用

# 结果为:
# ------ piece func -----------
  
  

form import 的形式:还是用做菜来说吧,你有一个朋友会做菜(模块名),一顿烧烤,你从他那里学会了几道菜(功能),你学会了之后,想做菜了,还需要找朋友来帮忙吗?!你要是觉得别人帮你理所应当我也没法!!!继续,你都会了,当然是自己下厨了(使用功能)。

from 模块名 import *

导入模块中的所有公开部分


from piece import *  # from 模块名import 星号 

func()  # 直接使用


看上面的代码和导入指定的功能没什么区别,那为什么说 星号 是导入所有公开部分和import 模块有什么区别呢?
首先,说一下from 模块名 import * 怎么理解,可以理解为你的朋友会做菜,会修车等等,你一顿烧烤学会做菜(公共的功能),但是他没教你修车(公共功能,但是我不想教你),所以你只会做菜(只能使用做菜,不能使用修车)。
通过上面的叙述应该可以明白 星号 是导入所有公开部分和import 模块的区别。区别在于找朋友帮忙,只要朋友会他就能帮你做(import)。但是你从朋友那里学 (from import *),他不教,你就不会。

那么有一个问题,星号是怎么知道你的朋友有哪些是想教给你,哪些不想的呢?__all__ 变量

__all__ 变量

通过前面可以知道__all__ 变量 的作用是控制 星号 可以导入的功能,也只对 星号 起作用。

piece.py


__all__ = ["func","func3"]  # __all__ 变量,赋值列表,列表中的每个元素都是功能名称的字符串
   
def func():
    print("------ piece func -----------")


def func2():
    print("------ piece func -----------")


def func3():
    print("------ piece func -----------")



使用 星号 导入


from piece import *

func()
func3()
func2()

# 结果为:
# ------ piece func -----------
# Traceback (most recent call last):
# ------ piece func3 -----------
#   File "E:/workspace/pycharm/pycharm/Demo.py", line 7, in <module>
#     func2()
# NameError: name 'func2' is not defined

# 结果分析:
# 通过结果可以看出,__all__ 变量中的功能都正常运行,不在__all__ 中的功能不能使用


模块与路径

导入模块,会了,那么导入模块是根据什么导入的呢?比如说系统有个random 模块,我的工程目录下有一个random 模块,是导入我工程目录下的random ,还是 系统中的random ?往下看



import piece
import sys
import os

print(piece.__file__)  # 模块有一个__file__属性,可以查看当前导入的模块的存放路径
print(os.getcwd())  # 获取当前工作路径
print(sys.path)  # 获取系统搜索导入模块会查看的路径
 
# 结果为:
# E:\workspace\pycharm\pycharm\piece.py
# E:\workspace\pycharm\pycharm
# ['E:\\workspace\\pycharm\\pycharm', 
# 'E:\\workspace\\pycharm\\pycharm', 'D:\\software\\Python36\\python36.zip', 
# 'D:\\software\\Python36\\DLLs', 'D:\\software\\Python36\\lib', 
# 'D:\\software\\Python36', 'D:\\software\\Python36\\lib\\site-packages']

# 结果分析:
# sys.path 搜索路径是一个列表,列表可以增删改查,列表的第一个元素是当前的工作路径,
# 所以当工作路径下有一个和系统模块重名的模块时,会导入工作路径下的模块。
# 问重名会不会有影响?首先不建议重名,那我怎么知道有没有重名?你不需要知道!为什么不需要知道?
# 首先你知道系统有random 模块,你才会用系统的,如果说系统没有这个模块或者你不知道有这个模块,
# 你还会用吗? 不会用吧?!那么在工作目录下创建一个random 模块来使用,有影响吗?


自定义模块与测试

自定义模块

通俗点说就是自己写一个 .py 的文件,文件中包含一些功能。

测试

在自己的模块中写测试代码,测试模块功能。

piece.py


def func():
    print("------ piece func -----------")


print(" piece 的测试")

# 结果:
#  piece 的测试  # 假设当前模块测试通过


piece.py 被当做模块导入

Demo.py 中导入piece 模块,直接运行Demo.py 文件


import piece

# 直接运行
# 结果为:
#  piece 的测试


Demo.py文件中只有一句import ,为什么会有输出?输出的结果是不是有点眼熟?这不是模块中的测试代码吗?
怎么解决这个问题?__name__变量

修改模块piece


def func():
    print("------ piece func -----------")


if __name__ == "__main__":
    print(" piece 的测试")

# 运行结果为:
# __main__
# piece 的测试


修改Demo.py


# import piece
# import piece as p

# 分别以 import形式 以及 别名形式导入
# 运行结果:
# piece
# piece
# 分析在piece 中直接运行的结果与piece 被当做模块导入Demo 文件中运行的结果可以发现
# 在piece 直接piece 本身时,__name__的值为__main__,
# 当piece 被当做模块导入Demo 文件中,运行Demo 文件时,piece 的__name__值为模块名,且不受别名的影响。


import 没有继承

piece1.py


def func():
    print("------ piece1 func -----------")


piece.py


import piece1


def func():
    print("------ piece func -----------")


if __name__ == '__main__':
    piece1.func()


Demo.py


import piece

if __name__ == '__main__':
    piece.func()
    piece1.func()

# 执行结果:
# ------ piece func -----------
# Traceback (most recent call last):
#   File "E:/workspace/pycharm/pycharm/Demo.py", line 5, in <module>
#     piece1.func()
# NameError: name 'piece1' is not defined


怎么理解呢?朋友(piece)的朋友(piece1)并不是你(Demo)的朋友

什么是包

包就是文件夹或者目录,作用:归类,将功能相类似或者相关联的模块放在同一包下,方便管理

在工程目录下新建文件夹,如果使用集成开发工具pytcharm 新建python package会自带__init__.py 文件,
这个文件有什么作用呢?

__init__.py文件

__init__.py 是包的一个初始化文件,可以提供一个__all__变量(和模块中的__all__变量类似),初始化模块所需环境,python2中必须有这个文件。

包名的格式

com.XXX1.XXX2.XXX3
. 的作用是分隔目录,如上有三个. 分隔了四层目录,com 下有XXX1,XXX1 下有XXX2 ,XXX2 下有XXX3

导入包中的模块

  • import 包名.模块名
  • from 包名.模块名 import 功能名

com.dragon_fang.demo 包下的模块 piece.py 的内容


def func():
    print("------ piece func -----------")


使用import 导入

com.dragon_fang 包下的Demo.py


import demo.piece  # impotent 包名.模块名,去找你的中国(包名)朋友(模块名)帮忙,导入指定的模块

demo.piece.func()  # 包名.模块名.功能名 使用,功能包括模块中的方法、变量、类等都可以使用。

# 结果为:
# ------ piece func -----------



# as 定义别名,结合import 使用 
import demo.piece as p  # 使用as 定义别名,当包的层级比较深时,很好用

p.func()  # 别名.功能名

# 结果为:
# ------ piece func -----------
  
  

form 模块名 import 功能


from demo import piece   # form 包名 import 模块名 ,导入指定的模块

piece.func()  # 直接使用

# 结果为:
# ------ piece func -----------
  


# as 结合 form import 使用

# from demo import piece as 别名,为指定的模块起一个别名
from demo import piece as p 

p.func()  # 别名.功能

# 结果为:
# ------ piece func -----------
  
  

from包名 import *

导入包中的所有公开部分


from demo import *  # from 包名 import 星号 

piece.func()  # 模块.功能


导入包中的模块的 import 和 from import 与 导入模块的 import 和 from import 类似,不做赘述。

说一下 *(星号) 前面说过,包下有一个__init__.py 文件,文件中有一个__all__ 变量控制 *(星号) 可以导入包中的哪些模块,
所有在__all__ 变量列表中以字符串存储的功能名才能被 *(星号) 导入。


到此结   DragonFang   2018.4.16

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,445评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,889评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,047评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,760评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,745评论 5 367
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,638评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,011评论 3 398
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,669评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,923评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,655评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,740评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,406评论 4 320
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,995评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,961评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,197评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,023评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,483评论 2 342

推荐阅读更多精彩内容

  • 一、模块 1、模块和导入 当程序代码量变得相当大、逻辑结构变得非常复杂的时候,我们最好把代码按照逻辑和功能划分成一...
    常大鹏阅读 2,968评论 0 9
  • 〇、前言 本文共108张图,流量党请慎重! 历时1个半月,我把自己学习Python基础知识的框架详细梳理了一遍。 ...
    Raxxie阅读 18,912评论 17 410
  • 组件的生命周期方法分以下三个阶段。 Mounting当创建组件的实例并将其插入到DOM中时,将调用这些方法:con...
    _八神光_阅读 1,085评论 0 0
  • 我怕我的孤勇错过了最好的选择,所以我只能跟着我的心走!
    人见人爱的甲壳虫阅读 145评论 0 0