異常、模塊、分發、插件化開發、插槽和反向等

異常、模塊、分發、插件化開發、插槽和反向等

————————————————異常————————————————–
異常
區分 異常和錯誤
產生異常
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.www58058.com/99154

(0)
JacoJaco
上一篇 2018-05-22
下一篇 2018-05-22

相關推薦

欧美性久久久久