目的是爲了便於共享。爲了更多項目調用使用,或者共享給別人,就須要打包,目的是爲了複用。python
Pypi(Python Package Index)公共的模塊存儲中心。https://pypi.python.org/pypi編程
(1)distutils 官方標準庫,使用安裝腳本setup.py來構建、安裝包。多線程
(2)setuptools 是替代distutils的加強版工具集,包含easy_install工具,使用ez_setup.py文件,支持egg格式的構建和安裝。框架
提供查詢,下載,安裝,構建,發佈,管理等包管理功能。函數
(3)Pip工具
Pip是目前包管理的事實標準。ui
構建在setuptools之上,替代easy_insall的,一樣提供豐富的包管理功能。url
(4)wheel插件
提供bdist_wheel做爲setuptools的擴展命令,這個命令能夠用來生成新打包格式wheel,線程
Pip開始提供了一個wheel子命令來安裝wheel包,必須先安裝wheel模塊,讓Python庫以二進制形式安裝,不須要再本地編譯。
首先建立一個setup.py文件,
內容:
from distutils.core import setup
setup(name='3',
version='0.1.1',
description = 'test',
author='wcl',
author_email='www.qq.com',
packages = ['3']
)
#name:名字
# version 版本
# packages=[]打包列表
# packages = ['3']指定之後,就會把全部的非目錄子模塊打包。
# ['m','m.m1.m2.m3'] 逐級創建目錄,可是隻是把m的全部非目錄子模塊打包。後面的也打包
#description 描述信息
#author 做者
#author_email做者郵件
#url 包的主頁,能夠不寫
查詢幫助命令:Python setup.py cmd -help
建立一個build目錄
#Python setup.py build
在項目目錄下多了build目錄,有一個lib子目錄,lib下就是模塊m的目錄。
全部的.py 文件所有被複制了,可是子目錄沒有被複制。
構建了一樣的目錄結構,並只是拷貝了__init__.py 文件。
build 獲得的文件,直接拷貝到其餘項目就可使用了。
打包的時候子包不要,模塊仍是要帶上的。 setup.build。Packages後面寫的是包名,而不是模塊名。
Build後就能夠install,直接運行
###Python setup.py install
若是沒有build,會先build編譯,而後安裝。
Sdist命令:
####Python setup.py sdist
建立源代碼的分發包
產生一個dist目錄,裏面生成一個帶版本號的壓縮包。
在其餘地方解壓縮文件,裏面有setup.py 就能夠直接使用 Python setup.py install 安裝了,也能夠 ##pip install xxxxxxxxxxx 直接使用pip安裝這個壓縮包。
製做window是下的分發包:Python setup.py bdist_wininst.
打包成rpm:Python setup.Py bdist_rpm
也能夠將寫好的模塊發佈到公共的pipy上,也能夠搭建pypi私服。
模塊名先後:優先級。
七、wheel包
安裝wheel依賴
## pip install wheel
from distutils.core import setup
from setuptools import setup
setup(name='3',
version='0.1.1',
description = 'test',
author='wcl',
author_email='www.qq.com',
packages = ['3']
)
分發一下,元代碼打包成zip包。
動態導入
運行時候,根據用戶需求(提供字符串),找到模塊的資源動態加載起來。
__import__ (name,globals=None,locals = None,fromlist=(),level=0)
Name模塊名
Import語句本質上就是調用這個函數,可是不鼓勵其直接使用,使用importlib.import_module().
Sys = _import__(‘sys’)
M2模塊:
class A:
def show(self):
print('A')
M1:模塊
if __name__ == '__main__':
mod = __import__('m2')
cls = getattr(mod,'A')
cls().show()
動態的調用
class A:
def show(self):
print('A')
import importlib
def load(name:str,sep='.'):
m,_,c = name.partition(sep)
mod = importlib.import_module(m)
cls = getattr(mod,c)
return cls()
if __name__ == '__main__':
a = load('m2.A')
a.show()
A
插件化的核心代碼。
依賴的技術
反射:運行時候獲取類型的信息,能夠動態維護類型數據。
動態import:推薦使用importlib模塊,實現動態import模塊的能力。
多線程:能夠開啓一個線程。等待用戶輸入,從而加載指定名稱的模塊。
1)程序啓動時候。啓動時候掃描固定的目錄,加載插件。
2)程序運行時。程序運行中,接受用戶指令或請求,啓動相應的插件。
兩個方式各有利弊,若是插件過多,會致使程序啓動很慢,若是用戶使用時候在加載,若是插件太大或者依賴多,插件將會啓動慢。
因此先加載經常使用的,必須的插件,其餘插件使用時候,發現須要,動態載入。
軟件的設計不可能盡善盡美,或者在某些功能上,不可能作的太專業了,須要專業的客戶本身加強。
接口和插件的區別:
接口每每是暴露出來的功能。例如模塊提供的函數或方法,加載模塊後調用這些函數完成功能。接口也是一種規範,約定了必須實現的功能(必須提供某名稱的函數),可是不關心怎麼實現這個功能。
插件是吧模塊加載到系統中,運行它,加強當前系統功能,或者提供系統不具有的功能,
每每插件技術應用在框架設計中,系統自己設計簡單化,輕量級,實現基本功能後,其餘功能經過插件加入進來,方便擴展。
問題的引出
字典爲了提高查詢效率,必須利用空間換時間。
通常來講一個對象,屬性多一點,都存儲在字典中便於查詢,問題不大。
對象數百萬個。字典佔用率就有些大了。
只要slots定義的,就會阻止了實例的字典,沒有了字典,裏面只能出現定義的屬性,沒有定義的一概不能使用。
class A:
X = 1
__slots__ = ('x','y')
def __init__(self,x,y):
self.x = x
self.y = y
def show(self):
print(self.x,self.y)
a = A(1,2)
a.show()
print('A',A.__dict__)
# print(a.__dict__) #字典被省略了
print(a.__slots__)
1 2
A {'y': <member 'y' of 'A' objects>, 'show': <function A.show at 0x000000972DAF4BF8>, '__init__': <function A.__init__ at 0x000000972DAF4D08>, '__doc__': None, 'x': <member 'x' of 'A' objects>, '__slots__': ('x', 'y'), 'X': 1, '__module__': '__main__'}
('x', 'y')
__slota__告訴解釋器,實例的屬性豆角什麼,通常來講,既要節約內存,最好仍是使用元組比較好。
並且實例不能夠動態增長屬性,類直接增長,由於__slots__是針對實例的。
只能限制當前類的實例,不能繼承使用。除非子類裏面本身也是定義了__slots__.
__slots__ = 後面寫元組比較好。
應用場景:
使用須要構建在數百萬以上的對象,且內存容量較爲緊張,實例的屬性檢查、固定缺不用動態增長的場景。
1)NotImplemented 未實現。是個值,單值。
2)NotImplementedError 未實現異常。
3)只有raise纔是無參數的構造。
print(type(NotImplemented))
print(type(NotImplementedError))
# raise NotImplemented #不可使用,顯示的是不屬於異常類
raise NotImplementedError
class A:
def __init__(self,x):
self.x = x
def __add__(self, other):
print(self,'add')
return self.x + other.x
def __iadd__(self, other):
print(self,'iadd')
return A(self.x + other.x)
def __radd__(self, other):
print(self,'radd')
try:
return self.x + other.x
except AttributeError:
try:
x = int(other)
except:
x= 0
return self.x + x
a = A(4)
# b = A(5)
1 + a
執行__radd__,實現1+a的方法。
字符串也是實現了__add__ 方法,不過默認處理不了和其餘類型的加法,因此就返回NotImplemented。