【Python五篇慢慢弹(4)】模块异常谈python

模块异常谈python

作者:白宁超

2016年10月10日12:08:31

摘要:继<快速上手学python>一文之后,笔者又将python官方文档认真学习下。官方给出的pythondoc入门资料包含了基本要点。本文是对文档常用核心要点进行梳理,简单冗余知识不再介绍,作者假使你用c/java/c#/c++任一种语言基础。本系列文章属于入门内容,老鸟可以略看也可以略过,新鸟可以从篇一<快速上手学python>先接触下python怎样安装与运行,以及pycharm编辑器的使用和配置;篇二<数据结构看python>介绍python语言中控制语句、列表、字典、元组、循环等基本操作;篇三<函数修行知python>细解python语言函数的范畴与内容;篇四<模块异常谈python>采用登录的案例详解模块来龙去脉;篇五<‘类’过依然继续前行,直至ending再出发>介绍类的基本操作,扩展虚拟环境、标准类库和下个系列预告。(本文原创,转载注明出处:模块异常谈知python)

目录:


【Python五篇慢慢弹(1)】快速上手学python
【Python五篇慢慢弹(2)】数据结构看python
【Python五篇慢慢弹(3)】函数修行知python
【Python五篇慢慢弹(4)】模块异常谈python
【Python五篇慢慢弹(5)】‘类’过依然继续前行,直至ending再出发

1 模块


【小记】本文中所有代码经过测试均可正常运行,python有个问题就是复制后会破坏原有格式。所以读者复制运行时报如下错误:SyntaxError: expected an indented block,是因为空格问题,可以预留4个空格,或者采用tab键空格

python脚本:如果你想要编写一些更大的程序,并把程序写入一个.py的文件作为执行文件。

模块定义:在脚本或者解释器的一个交互式实例中使用。这样的文件被称为模块;模块中的定义可以导入到另一个模块或主模块中。模块是包括 Python 定义和声明的文件。文件名就是模块名加上.py 后缀。模块的模块名可以由全局变量 __name__(类似主函数)得到。

登陆权限限制实例解析模块
实例分析

通过前面文章介绍python基本语法和例子,大家对python已经不陌生了。现在咱们做一个登录的案例,要求如下:

①创建脚本:在pycharm(快速上手学python 有介绍)或者IDLE(python 3.5)中创建一个LoginDome.py

②登录函数:定义一个login()函数,当用户输入用户名密码同时匹配时,登录成功,反之登录失败。3次机会不成功锁定账号。

③信息收集:每次登录的用户名和密码放在一个列表里面。

④模块测试:完成以上案例后,使用pycharm自动对类创建测试单元

⑤模块调用:新建一个moduleTest.py去调用之前的login()函数

实例演示:LoginDome.py 的文件,录入如下内容

#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
__title__ = ''
__author__ = 'cuitbnc'
__mtime__ = '2016/10/4'
# 欢迎进入我的主页:http://www.cnblogs.com/baiboy/.
""" '''默认函数值:最常用的一种形式是为一个或多个参数指定默认值
username:必选参数,用户名
password:必选参数,密码
limits:可选参数,登陆权限限制
complaint:可选参数,登陆错误,剩余次数提示
urs=[] :字典参数
'''
def login(username,password, limits=3, complaint='you have login times:【',urs=[]):
countlimits = limits; #统计自定义限制次数
while True:
usrname= input(username)
usrpwd=input(password)
urs.append("you input data:["+usrname+"-"+usrpwd+"]") # 记录用户每次登录的信息
print(urs)
if usrname in ('admin', 'ad', 'bnc') and usrpwd in ('pass', 'pwd', 'password', 'bnc'):
print('Congratulations,Welcome 【'+usrname+'】to the login page.')
return
else:
print('Sorry,【'+usrname+'】:you username or password error.')
limits = limits - 1
if limits == 0:
print('More '+str(countlimits)+' times,Your account is locked!')
return
print(complaint+str(limits)+"】times")

1、只给出必要的参数运行结果:

# 只给出必要的参数:
login('UserName:\t','PassWord:\t')

 【Python五篇慢慢弹(4)】模块异常谈python

解析:

默认函数值:最常用的一种形式是为一个或多个参数指定默认值,当只输入必选参数时候默认登陆权限是3次,登陆错误的提示也是默认值。具体效果如上图

2、给出必要的参数和权限次数限制运行结果:

# 给出一个可选的参数
login('UserName:\t','PassWord:\t',2)

 【Python五篇慢慢弹(4)】模块异常谈python

解析: 

可选参数咱们手动设置2次,运行效果如图。

3、给出必选参数,限制权限2次,且自定义给出错误提示运行效果:

# 或者给出所有的参数
login('UserName:\t','PassWord:\t', 2, 'Remember you enter the correct user name and password,you have login times:')

【Python五篇慢慢弹(4)】模块异常谈python

解析:

自定义的错误提示如图所示。

自动创建模块的单元测试:

1)选中login函数名,按下Ctrl+Shift+T,或者Navigate → Test自动生成测试类

【Python五篇慢慢弹(4)】模块异常谈python

2)自动生成效果如下图:pass没有具体含义,占位符理解。

【Python五篇慢慢弹(4)】模块异常谈python

3)运行测试类结果:

【Python五篇慢慢弹(4)】模块异常谈python

模块调用:

1)新建一个Python文件命名moduleTest.py,录下以下代码

#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
__title__ = ''
__author__ = 'cuitbnc'
__mtime__ = '2016/10/9'
# 欢迎进入我的主页:http://www.cnblogs.com/baiboy/.
"""
import LoginDome
LoginDome.login('UserName:\t\n','PassWord:\t\n')

运行结果:

【Python五篇慢慢弹(4)】模块异常谈python

注意:运行调用模块名.方法名([形参])

2、深入模块


模块(py文件名)全局变量的使用:modname.itemname
模块导入的几种方式
①import ModuleName
②from ModuleName import MethodName1, MethodName1
③from ModuleName import * (不推荐,这样导入后代码没有那么清晰,不过交互式时候可以用)
注意:出于性能考虑,每个模块解释器会话中只导入一遍。因此,如果你修改了你的模块,需要重启解释器;或者可以用 imp.reload() 重新加载,例如 import imp; imp.reload(modulename)。

模块的搜索路径
导入一个叫LoginDome的模块时,解释器先在当前目录中搜索名为LoginDome.py 的文件。如果没有找到的话,接着会到 sys.path 变量中给出的目录列表中查找。
sys.path 变量的初始值来自如下:
输入脚本的目录(当前目录)。
环境变量 PYTHONPATH 表示的目录列表中搜索
实际上,解释器由 sys.path 变量指定的路径目录搜索模块,该变量初始化时默认包含了输入脚本(或者当前目录), PYTHONPATH 和安装目录。

编译的” Python 文件
为了加快加载模块的速度,Python 会在 __pycache__ 目录下以 module.version.pyc 名字缓存每个模块编译后的版本,这里的版本编制了编译后文件的格式。它通常会包含 Python 的版本号。
例如,在 CPython 3.3 版中,spam.py 编译后的版本将缓存为 __pycache__/spam.cpython-33.pyc。这种命名约定允许由不同发布和不同版本的 Python 编译的模块同时存在。
Python 会检查源文件与编译版的修改日期以确定它是否过期并需要重新编译。这是完全自动化的过程。同时,编译后的模块是跨平台的,所以同一个库可以在不同架构的系统之间共享。
Python 不检查在两个不同环境中的缓存。首先,它会永远重新编译而且不会存储直接从命令行加载的模块。其次,如果没有源模块它不会检查缓存。若要支持没有源文件(只有编译版)的发布,
编译后的模块必须在源目录下,并且必须没有源文件的模块。
部分高级技巧
1 为了减少一个编译模块的大小,你可以在 Python 命令行中使用 -O 或者 -OO。-O 参数删除了断言语句,-OO 参数删除了断言语句和 __doc__ 字符串。因为某些程序依赖于这些变量的可用性,你应该只在确定无误的场合使用这一选项。“优化的” 模块有一个 .pyo 后缀而不是 .pyc 后缀。未来的版本可能会改变优化的效果。
2 来自 .pyc 文件或 .pyo 文件中的程序不会比来自 .py 文件的运行更快;.pyc 或 .pyo 文件只是在它们加载的时候更快一些。
3 compileall 模块可以为指定目录中的所有模块创建 .pyc 文件(或者使用 -O 参数创建 .pyo 文件)。

标准模块
Python 带有一个标准模块库,并发布有独立的文档,名为 Python 库参考手册。
例如,winreg 模块只提供在 Windows 系统上才有。有一个具体的模块值得注意: sys ,这个模块内置于所有的 Python 解释器。变量 sys.path和 sys.version

>>> import sys
>>> sys.path
['', 'E:\\Python\\Lib\\idlelib', 'E:\\Python\\python35.zip', 'E:\\Python\\DLLs', 'E:\\Python\\lib', 'E:\\Python', 'E:\\Python\\lib\\site-packages']
>>> sys.version
'3.5.2 (v3.5.2:4def2a2901a5, Jun 25 2016, 22:01:18) [MSC v.1900 32 bit (Intel)]'

变量 sys.path 是解释器模块搜索路径的字符串列表。它由环境变量 PYTHONPATH 初始化,如果没有设定 PYTHONPATH ,就由内置的默认值初始化。你可以用标准的字符串操作修改它:

3、dir() 函数


内置函数 dir() 用于按模块名搜索模块定义,它返回一个字符串类型的存储列表

dir()内置函数实例:dir() 不会列出内置函数和变量名。如果你想列出这些内容,它们在标准模块 builtins 中定义
import sys,LoginDome,builtins
print("LoginDome 内置函数:"+str(dir(LoginDome)))
print("Sys 内置函数:"+str(dir(sys)))
print("builtins 内置函数变量名:"+str(dir(sys)))

LoginDome 内置函数

['__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', 'login']

Sys 内置函数:

['__displayhook__', '__doc__', '__excepthook__', '__interactivehook__', '__loader__', '__name__', '__package__', '__spec__', '__stderr__', '__stdin__', '__stdout__', '_clear_type_cache', '_current_frames', '_debugmallocstats', '_getframe', '_home', '_mercurial', '_xoptions', 'api_version', 'argv', 'base_exec_prefix', 'base_prefix', 'builtin_module_names', 'byteorder', 'call_tracing', 'callstats', 'copyright', 'displayhook', 'dllhandle', 'dont_write_bytecode', 'exc_info', 'excepthook', 'exec_prefix', 'executable', 'exit', 'flags', 'float_info', 'float_repr_style', 'get_coroutine_wrapper', 'getallocatedblocks', 'getcheckinterval', 'getdefaultencoding', 'getfilesystemencoding', 'getprofile', 'getrecursionlimit', 'getrefcount', 'getsizeof', 'getswitchinterval', 'gettrace', 'getwindowsversion', 'hash_info', 'hexversion', 'implementation', 'int_info', 'intern', 'is_finalizing', 'maxsize', 'maxunicode', 'meta_path', 'modules', 'path', 'path_hooks', 'path_importer_cache', 'platform', 'prefix', 'set_coroutine_wrapper', 'setcheckinterval', 'setprofile', 'setrecursionlimit', 'setswitchinterval', 'settrace', 'stderr', 'stdin', 'stdout', 'thread_info', 'version', 'version_info', 'warnoptions', 'winver']

builtins 内置函数变量名:

['__displayhook__', '__doc__', '__excepthook__', '__interactivehook__', '__loader__', '__name__', '__package__', '__spec__', '__stderr__', '__stdin__', '__stdout__', '_clear_type_cache', '_current_frames', '_debugmallocstats', '_getframe', '_home', '_mercurial', '_xoptions', 'api_version', 'argv', 'base_exec_prefix', 'base_prefix', 'builtin_module_names', 'byteorder', 'call_tracing', 'callstats', 'copyright', 'displayhook', 'dllhandle', 'dont_write_bytecode', 'exc_info', 'excepthook', 'exec_prefix', 'executable', 'exit', 'flags', 'float_info', 'float_repr_style', 'get_coroutine_wrapper', 'getallocatedblocks', 'getcheckinterval', 'getdefaultencoding', 'getfilesystemencoding', 'getprofile', 'getrecursionlimit', 'getrefcount', 'getsizeof', 'getswitchinterval', 'gettrace', 'getwindowsversion', 'hash_info', 'hexversion', 'implementation', 'int_info', 'intern', 'is_finalizing', 'maxsize', 'maxunicode', 'meta_path', 'modules', 'path', 'path_hooks', 'path_importer_cache', 'platform', 'prefix', 'set_coroutine_wrapper', 'setcheckinterval', 'setprofile', 'setrecursionlimit', 'setswitchinterval', 'settrace', 'stderr', 'stdin', 'stdout', 'thread_info', 'version', 'version_info', 'warnoptions', 'winver']

4、包


包(模块集):用“圆点模块名”的结构化模块命名空间。例如, A.B 的模块表示了名为 A 的包中名为 B 的子模块。不同的模块架构可以避免冲突,

模块集统一处理声音文件和声音数据。存在几种不同的声音格式(例如:.wav, .aiff,.au )。可能你还想要对声音数据做很多不同的操作(例如混音,添加回声,应用平衡 功能,创建一个人造效果),所以你要加入一个无限流模块来执行这些操作。你的包可能会是这个样子:

sound/                          Top-level package
__init__.py Initialize the sound package
formats/ Subpackage for file format conversions
__init__.py
wavread.py
wavwrite.py
aiffread.py
aiffwrite.py
auread.py
auwrite.py
...
effects/ Subpackage for sound effects
__init__.py
echo.py
surround.py
reverse.py
...
filters/ Subpackage for filters
__init__.py
equalizer.py
vocoder.py
karaoke.py

当导入这个包时,Python 通过 sys.path 搜索路径查找包含这个包的子目录。为了让 Python 将目录当做内容包,目录中必须包含 __init__.py 文件。当然它也可以执行包的初始化代码,或者定义稍后介绍的 __all__ 变量。

导入包的几种方式:
①导入包里的特定模块:
例如:import sound.effects.echo (导入 sound.effects.echo 子模块)
调用:sound.effects.echo.echofilter(input, output, delay=0.7, atten=4)
②导入包可以选择方式
例如:from sound.effects import echo
调用: echo.echofilter(input, output, delay=0.7, atten=4)
③直接导入函数或变量
例如:from sound.effects.echo import echofilter (直接调用它的 echofilter() 函数)
调用:echofilter(input, output, delay=0.7, atten=4)

导包原理:使用 from package import item 方式导入包时,这个子项(item)既可以是包中的一个子模块(或一个子包),也可以是包中定义的其它命名,像函数、类或变量。import 语句首先核对是否包中有这个子项,如果没有,它假定这是一个模块,并尝试加载它。如果没有找到它,会引发一个 ImportError 异常。相反,使用类似 import item.subitem.subsubitem 这样的语法时,这些子项必须是包,最后的子项可以是包或模块,但不能是前面子项中定义的类、函数或变量。

从 * 导入包
import 语句执行from package import * 时,如果包中的 __init__.py 代码定义了一个名为 __all__ 的列表,就会按照列表中模块名进行导入。新版本的包发布可以任意更新__all__列表。如果包作者不想 import * 的时候导入他们的包中所有模块,那么也可能会决定不支持它( import * )。
例如, sound/effects/__init__.py 这个文件可能包括如下代码:__all__ = ["echo", "surround", "reverse"]
这意味着 from Sound.Effects import * 语句会从 sound 包中导入以上三个已命名的子模块。

包内引用
例如: sound.filters.vocoder 包需要使用 sound.effects 包中的 echo 模块,它可以 from Sound.Effects import echo。包内引用可以.代表上级目录
from . import echo 等于 (from Sound.Effects import echo)
from .. import formats 等于 (from Sound import formats)
from ..filters import equalizer 等于(from Sound.filters import equalizer)
需要注意的是显式或隐式相对位置导入都基于当前模块的命名。因为主模块的名字总是 "__main__",Python 应用程序的主模块应该总是用绝对导入。

5、错误和异常


errors:语法错误
exceptions:异常
例子:它会一直要求用户输入,直到输入一个合法的整数为止,但允许用户中断这个程序。注意:用户产生的中断会引发一个 KeyboardInterrupt 异常。

>>> while True:
try:
x = int(input("Please enter a number: "))
break
except ValueError:
print('oh,That was no valid number. Try again...') Please enter a number: rttr
oh,That was no valid number. Try again...
Please enter a number:

try 语句按如下工作方式

  1. 执行 try 子句 (在 try 和 except 关键字之间的部分)。
  2. 如果没有异常发生, except 子句 在 try 语句执行完毕后就被忽略了。
  3. 如果在 try 子句执行过程中发生了异常,那么该子句其余的部分就会被忽略。如果异常匹配于 except 关键字后面指定的异常类型,就执行对应的except子句。然后继续执行 try 语句之后的代码。
  4. 如果发生了一个异常,在 except 子句中没有与之匹配的分支,它就会传递到上一级 try 语句中。如果最终仍找不到对应的处理语句,它就成为一个 未处理异常,终止程序运行,显示提示信息。

一个 try 语句可能包含多个 except 子句,分别指定处理不同的异常。例如:(RuntimeError, TypeError, NameError)最后一个 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 ... except 语句可以带有一个 else子句,该子句只能出现在所有 except 子句之后。当 try 语句没有抛出异常时,需要执行一些代码,可以使用这个子句。例如:

for arg in sys.argv[1:]:
try:
f = open(arg, 'r')
except IOError:
print('cannot open', arg)
else:
print(arg, 'has', len(f.readlines()), 'lines')
f.close()

异常处理器不仅仅处理那些在 try 子句中立刻发生的异常,也会处理那些 try 子句中调用的函数内部发生的异常。例如:

>>> def this_fails():
... x = 1/0
>>> try:
... this_fails()
... except ZeroDivisionError as err:
... print('Handling run-time error:', err)
Handling run-time error: int division or modulo by zero

抛出异常:raise 语句允许程序员强制抛出一个指定的异常。例如:

>>> try:
raise NameError('There name error')
except NameError:
print('An exception flew by!')
raise An exception flew by!
Traceback (most recent call last):
File "<pyshell#196>", line 2, in <module>
raise NameError('There name error')
NameError: There name error

定义清理行为

程序:
【Python五篇慢慢弹(4)】模块异常谈python

运行结果:
【Python五篇慢慢弹(4)】模块异常谈python

预定义清理行为
读取文件:(文件操作将在下篇介绍

读取文件:
for line in open("myfile.txt"):
print(line)
如上文件读取没有关闭,则可以采用之前文章介绍的预处理with解决:
with open("myfile.txt") as f:
for line in f:
print(line)

6、参考文献和推荐资料


  1. Python 官方网站 :包含代码、文档和 Web 上与 Python 有关的页面链接该网站镜像于全世界的几处其它问题,类似欧洲、日本和澳大利亚。镜像可能会比主站快,这取决于你的地理位置
  2. 快速访问 Python 的文档
  3. Python 包索引 :索引了可供下载的,用户创建的 Python 模块。如果你发布了代码,可以注册到这里,这样别人可以找到它
  4. The Scientific Python : 项目包括数组快速计算和处理模块,和大量线性代数、傅里叶变换、非线性solvers、随机数分布,统计分析以及类似的包
  5. 官方python学习文档
  6. 简明Python教程
  7. 廖雪峰:python教程
  8. Python官网文档
  9. 【51cto学院,入门课程】Python零基础入门学习视频教程
  10. 【个人博客:案例】GitHub数据提取与分析
  11. 【csdn】python知识库
  12. 【社区】python中文学习大本营
  13. 【个人博客】老王python
  14. 【51cto学院,网站开发】*辅仁大学:Python Django基础视频课程
上一篇:JSP标准标签库(JSTL)--JSTL简介与安装


下一篇:【Python五篇慢慢弹(3)】函数修行知python