事實上,addsitedir()
不處理zip文件;但它應該很容易複製行爲。
參見site.addsitedir()
源代碼;代碼只是試圖調用路徑上os.listdir()
來然後發現.pth
文件:
try:
names = os.listdir(sitedir)
except os.error:
return
dotpth = os.extsep + "pth"
names = [name for name in names if name.endswith(dotpth)]
for name in sorted(names):
addpackage(sitedir, name, known_paths)
其中addpackage()
只是site.addpackage()
。您可以將上述names
列表替換爲您的zip文件中的.pth
文件列表。您還必須複製site.addpackage()
行爲,該功能期望能夠讀取.pth
文件。
簡化,該函數的作用:
with f:
for n, line in enumerate(f):
if line.startswith("#"):
continue
if line.startswith(("import ", "import\t")):
exec line
continue
line = line.rstrip()
dir, dircase = makepath(sitedir, line)
if not dircase in known_paths and os.path.exists(dir):
sys.path.append(dir)
known_paths.add(dircase)
與例外處理混合makepath()
是site.makepath()
,和known_paths
確保找到的任何路徑僅加入一次。
因此,在本質上,通過.pth
命名所有項目都添加到您的sys.path
但執行任何開始import
那裏,然後,給.pth
文件勾入site.py
裝載階段。
import
掛鉤被基於setuptools
的包使用來構建命名空間包;這裏是一個從zc
命名空間的軟件包:
import sys,types,os; p = os.path.join(sys._getframe(1).f_locals['sitedir'], *('zc',)); ie = os.path.exists(os.path.join(p,'__init__.py')); m = not ie and sys.modules.setdefault('zc',types.ModuleType('zc')); mp = (m or []) and m.__dict__.setdefault('__path__',[]); (p not in mp) and mp.append(p)
它創建在sys.modules
使用sitedir
局部變量從addpackage()
功能的空模塊對象。請注意撥打os.path.exists()
;對於壓縮的雞蛋來說,這會失敗(不會添加空模塊對象),因此您可能需要檢測命名空間包併爲其提供自己的版本。 zc
名稱空間中的任何程序包只是確保有一個ModuleType()
對象用於它關心的父命名空間,__path__
屬性指向{sitedir}/{packagename}/__init__.py
。
另一種方法是將命名空間的包合併成一個目錄結構來代替。
你不能將namespaced egg合併到一個目錄結構中嗎? – 2013-05-05 20:44:33
我確實可以,但我想要一個更通用的解決方案(並且每次我想要打包新項目或添加新的依賴項時都不需要*不同* Makefile黑客)。 – quodlibetor 2013-05-05 20:46:45
這就是解決方法I在任何情況下都會考慮。 :-) – 2013-05-05 20:47:41