[英]Mask a python submodule from its package's __init__.py
一個特定的設置要求我在__init__.py
中創建局部變量,該局部變量應屏蔽同一軟件包中的模塊。
例如,變量y
(在__init__.py
的本地上下文中)將隱藏模塊y.py
import xy
語句應產生局部變量,而不是加載模塊。
如果您不想閱讀有關特定設置的信息,請向下滾動至該問題; 沒有細節是可以理解的。
我已經實現了一組Python 2.7軟件包,每個軟件包都可能需要單獨的配置設置。 為了方便起見,我計划為每個程序包提供配置默認值,任何使用其中一個程序包的人都可以在本地覆蓋它們。
(這樣做的理由是在將應用程序部署到運行特定環境的機器(服務器,工作站,筆記本電腦等)時分發默認設置,但同時允許覆蓋配置而不會弄亂本地存儲庫或重置本地對代碼更新的適應。)
目錄結構示例為:
~/pkg/
|
+- package_a/
| |
| +- __init__.py
| +- mod_x.py
| +- mod_y.py
|
+- package_b/
| |
| +- __init__.py
| +- mod_z.py
|
+- config/
| |
| +- __init__.py
| +- package_a.py # Should locally override <pkg>_sample.py
| +- package_a_sample.py
| +- package_b_sample.py
|
+- test_this.py
我想訪問存儲在config/
下的設置,例如常規模塊導入,例如:
# ~/pkg/test_this.py
import config.package_a as cfg_a
...但如果存在,則隱式切換到覆蓋文件。
為了使流程自動化,我動態創建了指向正確配置文件導入的局部變量。 使用imp
包,我可以導入一個模塊,並同時專門命名它。 (即在運行時,您無法區分是加載了<pkg>_sample.py
還是<pkg>.py
來提供配置。)
我終於結束了:
# ~/pkg/config/__init__.py
import os
import imp
__all__ = ['datastore']
_cfgbase = os.path.dirname(os.path.realpath(__file__))
for cfgmodule in __all__:
if os.path.isfile(os.path.join(_cfgbase, cfgmodule + '.py')):
locals()[cfgmodule] = imp.load_source(
cfgmodule, os.path.join(_cfgbase, cfgmodule + '.py'))
else:
locals()[cfgmodule] = imp.load_source(
cfgmodule, os.path.join(_cfgbase, cfgmodule + '_sample.py'))
實際上,這將創建對所需源文件的本地引用(當config/
存在<pkg>.py
時,省略<pkg>_sample.py
。
如果from config import package_a as cfg_a
使用,我可以在其他模塊/腳本中使用它。
本質上,這個問題可以歸結為眾所周知的import xy vs from x import y
-thing。
但是這里有所不同。
我知道import xy
要求y
是一個模塊。 是否有可能將模塊隱藏在其包的__init__.py
並在導入時提供局部變量instad?
from x import y
從x
的__init__.py
產生局部變量y
__init__.py
存在局部變量y
, import xy
始終會導入模塊。 我不能強迫每個人都始終使用前一個import語句,人們喜歡在其代碼中使用后一個import語句。
有什么建議嗎?
編輯:固定標題。 抱歉。
感謝@ martijn-pieters指出sys.modules
。
實際上,如果沒有正確命名新導入,我的方法就無需將新導入顯式添加到sys.modules
即可完美地工作:
locals()[cfgmodule] j= imp.load_source(
'config.' + cfgmodule, os.path.join(_cfgbase, cfgmodule + '.py'))
這樣就解決了這個問題,因為它沒有使用標准名稱(這里為package_a
)注冊新的子模塊,而是將其注冊為我的config
包的子模塊。
非常感謝!
import xy
並不需要y
作為模塊。 import xy
在sys.modules
結構中查找'x'
和'x.y'
鍵。 如果兩者都找到,則x
綁定到sys.modules['x']
。 只有當'x.y'
不存在時,Python才會尋找要加載的模塊。
然后,訣竅是將y
塞入sys.modules
:
sys.modules['x.y'] = y
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.