异常、模块、分发、插件化开发、插槽和反向等

异常、模块、分发、插件化开发、插槽和反向等

————————————————异常————————————————–
异常
区分 异常和错误
产生异常
raise语句显示的抛出异常,BaseException类的子类或实例
Python解释器检测到异常并引发

异常捕获:
try:
待捕获异常的代码块
except [异常类型]:
异常的处理代码块

异常类及继承层次
BaseException
递归代码
def exc_hierarchy(exc=BaseException, level=-1):
name = exc.__name__
if level == -1:
print(name)
else:
print(“{} +– {}”.format(‘ ‘ * level, name))
for sub in exc.__subclasses__():
exc_hierarchy(sub, level+1)

所有内建异常类的基类 BaseException
SysemExit
sys.exit()

KeyboardInterrupt
Exception 内建的、非系统退出的、自定义的异常都继承它
SyntaxError 语法错误
ArithmeticError 算术错误
LookupError 映射异常 IndexError KeyError
自定义异常

class MyException(Exception):
pass

try:
raise MyException()
except MyExcetion:
print(‘catch the exception’)

except 可以捕获多个异常
从小到大 从具体到宽泛

finally子句 无论如何都会执行
清理、释放工作

异常传递:由内层到外层 进行捕获处理

#线程中测试异常
import threading
import time

def foo1():
return 1/0

def foo2():
time.sleep(5)
print(‘foo2 start’)
foo1()
print(‘foo2 stop’)

t = threading.Thread(target=foo2)
t.start()

while True:
time.sleep(1)
print(‘Everything OK’)
if t.is_alive():
print(‘alive’)
else:
print(‘dead’)
break

try嵌套:
由内向外传递和捕获
如果内层有finally且有return break 语句,异常就不向外层抛出
def foo():
try:
ret = 1/0
except KeyError as e:
print(e)
finally:
print(‘inner fin’)
return #异常被丢弃

try:
foo()
except:
print(‘outer catch’)
finally:
print(‘outer fin’)

异常的捕获时机
1、立即捕获
立刻返回明确的结果
def parse_int(s):
try:
return int(s)
except:
return 0
print(parse_int(‘s’))

2、边界捕获
封装产生了边界 最外层必须处理异常

else子句 没有异常则执行

标准模式:
try:
<语句> #运行别的代码
except <异常类>:
<语句> #捕获某种类型的异常
except <异常类> as <变量名>:
<语句> # 捕获某种异常的类型并获得对象
else:
<语句> #如果没有异常发生
finally:
<语句> #退出try时总会执行

————————————————模块化———————————————

模块化
代码组织方式:库、包、模块
Python: 模块module 源代码文件
包package, 包名同名的目录及相关文件

import module[.module] 必须是模块
import module[.module] as … 模块别名
部分导入
from…import…
from…import…as…

看名词空间或属性 dir()
from functools import wraps as wr, partial
from os.path import exists
getattr(os.path, ‘exists’)
from pathlib import path

导入顶级模块,其名称加入本地名词空间,并绑定到模块对象
导入非顶级模块,只将顶级模块名称加入名词空间,访问要限定名称,例如:os.path

自定义模块:.py文件就是一个模块
模块名(即文件名)命名规范同标识符:数字、字母、下划线,非数字开头,通常全小写。

使用sys.path查看模块搜索顺序
程序主目录–主程序脚本所在目录–环境变量PYTHONPATH设置的目录–标准库目录–自带的库模块目录

sys.modules是存储所有加载的模块的字典

模块运行
特殊变量 __name__
解释器初始化:会初始化sys.modules字典、创建builtins(全局函数、常量)模块、__main__模块、sys模块以及模块搜索路径sys.path

if __name__ == “__main__” :用途
1、功能测试:作为非主模块,测试模块里的函数、类
2、避免主模块变更副作用:未封装的代码被执行了

模块的属性
__file__ 源文件路径
__cached__ 编译后字节码文件路径
__spec__ 模块的规范
__name__ 模块名
__package__ 模块是包,同__name__; 否则,可以设置为顶级模块的空字符窜


特殊的模块
Pycharm —project—new—python package

代码写在 __init__.py中
模块目录和子文件 、子模块

导入子模块一定会加父模块,但导入父模块一定不会导入子模块
包目录之间只能使用.点作为间隔,表示层级关系
封装:模块、函数、类、变量

模块是命名空间,内部的顶层标识符都是它的属性,可以通过__dict__或dir(module)查看
包是特殊的模块,包含__path__属性

区分 from json import encoder 名词空间无json json.dump无法使用
import json.encoder 名词空间有json json.dump 可以使用

绝对导入
模块名称前不是.开头
去搜索路径中找

相对导入
只能包内使用,用from语句
. 当前目录
.. 上一级目录
… 上上一级
顶层模块中不要使用相对导入

访问控制
模块内的标识符:
普通变量、保护变量、私有变量、特殊变量,都没有被隐藏

控制导入的模块:
1、from xyx import *
模块编写尽量加入 __all__ 控制导入的模块,下划线开头模块、相对引用包的子模块也可以加入

2、from module import name1, name2
知道要导入的模块

模块变量的修改:注意其他使用影响

———————————————————–分发——————————————————

包管理–分发
发布和共享,目的为了复用。
官方仓库中心:Pypi(Python Package Index), https://pypi.python.org/pypi

主要工具
distutils: 使用setup.py来构建、安装包,2000年停止开发。
setuptools:使用ez_setup.py文件。支持egg的构建安装。提供查询、下载、安装、构建、发布、管理等包管理功能。
pip:从Python3.4开始直接包含在安装文件里。
wheel:二进制形式安装Python库,无需本地编译。

方法:
参考例子:
https://docs.python.org/3.5/distutils/setupscript.html

#!/usr/bin/env python

from distutils.core import setup

setup(name=’Distutils’,
version=’1.0′,
description=’Python Distribution Utilities’,
author=’Greg Ward’,
author_email=’gward@python.net’,
url=’https://www.python.org/sigs/distutils-sig/’,
packages=[‘distutils’, ‘distutils.command’],
)

建包:$python setup.py build
注意每个层级的包都要打包

安装:$python setup.py install

分发:$python setup.py sdist
$python setup.py bdist_wininst #windows下的分发包
$python setup.py bdist_rpm #打包成rpm

——————————————–插件化开发——————————————–
插件化开发:
接口:约定规范,暴露功能, api
插件:加载到系统中,提供或增强某功能

核心代码示例:
importlib.import_module()
#importlib.import_module(name, package=None)

#主程序模块test.py
import importlib

def plugin_load(plugin_name:str, sep=”:”):
m, _, c = plugin_name.partition(sep)
mod = importlib.import_module(m)
cls = getattr(mod, c)
return cls()

if __name__ == “__main__”:
#装载插件
a = plugin_load(“test1:A”)
a.showme()

———————————————-插槽和反向—————————————-

基础知识补充:
__slots__ 插槽,规定了实例的属性,实例无需创建__dict__存储属性,从而在数据规模较大时节省内存。而且,在类被继承时,它不会继承。

区分 NotImplemented, 单值,是NotImplementedType类的实例
NotImplementedError 是类型,是异常, 返回type

运算符重载的反向方法:例如 __radd__

本文来自投稿,不代表Linux运维部落立场,如若转载,请注明出处:http://www.178linux.com/99154

发表评论

登录后才能评论

联系我们

400-080-6560

在线咨询:点击这里给我发消息

邮件:1823388528@qq.com

工作时间:周一至周五,9:30-18:30,节假日同时也值班