創建一個軟件包(package)似乎已經足夠簡單了,也就是在文件目錄下搜集一些模塊,再加上一個__init__.py文件,對吧?我們很容易看出來,隨著時間的推移,通過對軟件包的越來越多的修改,一個設計很差的軟件包可能會出現循環依賴問題,或是可能變得不可移植和不可靠。
1. __init__.py 僅為導入服務
對于一個簡單的軟件包,你可能會忍不住把工具方法,工廠方法和異常處理都丟進__init__.py,千萬別這樣!
一個結構良好的__init__.py文件,僅為一個非常重要的目的來服務:從子模塊導入。你的__init__.py應該看起來像這個樣子:
# ORDER MATTERS HERE -- SOME MODULES ARE DEPENDANT ON OTHERS# 導入順序要考慮——一些模塊會依賴另外的一些from exceptions import FSQError, FSQEnvError, FSQEncodeError, FSQTimeFmtError, FSQMalformedEntryError, FSQCoerceError, FSQEnqueueError, FSQConfigError, FSQPathError, FSQInstallError, FSQCannotLockError, FSQWorkItemError, FSQTTLExpiredError, FSQMaxTriesError, FSQScanError, FSQDownError, FSQDoneError, FSQFailError, FSQTriggerPullError, FSQHostsError, FSQReenqueueError, FSQPushError # constants relies on: exceptions, internalimport constants # const relies on: constants, exceptions, internalfrom const import const, set_const # has tests # path relies on: exceptions, constants, internalimport path # has tests # lists relies on: pathfrom lists import hosts, queues #...
2.使用__init__.py來限制導入順序
把方法和類置于軟件包的作用域中,這樣用戶就不需要深入軟件包的內部結構,使你的軟包變得易用。 作為調和導入順序的唯一地方。使用得當的話,__init__.py 可以為你提供重新組織內部軟件包結構的靈活性,而不需要擔心由內部導入子模塊或是每個模塊導入順序所帶來的副作用。因為你是以一個特定的順序導入子模塊,你的__init__.py 對于他程序員來講應該簡單易懂,并且能夠明顯的表示該軟件包所能提供的全部功能。
文檔字符串,以及在軟件包層面對__all__屬性的賦值應當是__init__.py中唯一的與導入模塊不相關的代碼:
__all__ = [ 'FSQError', 'FSQEnvError', 'FSQEncodeError', 'FSQTimeFmtError', 'FSQMalformedEntryError', 'FSQCoerceError', 'FSQEnqueueError', 'FSQConfigError', 'FSQCannotLock', 'FSQWorkItemError', 'FSQTTLExpiredError', 'FSQMaxTriesError', 'FSQScanError', 'FSQDownError', 'FSQDoneError', 'FSQFailError', 'FSQInstallError', 'FSQTriggerPullError', 'FSQCannotLockError', 'FSQPathError', 'path', 'constants', 'const', 'set_const', 'down', 'up', # ... ]
3.使用一個模塊來定義所有的異常
你也許已經注意到了,__init__.py中的第一個導入語句從exceptions.py子模塊中導入了全部的異常。從這里出發,你將看到,在大多數的軟件包中,異常被定義在引起它們的代碼附近。盡管這樣可以為一個模塊提供高度的完整性,一個足夠復雜的軟件包會通過如下兩種方式,使得這一模式出現問題。
新聞熱點
疑難解答