當前位置:
首頁 > 最新 > sys.path源碼分析

sys.path源碼分析

先說sys.path初始化結果:

*.pth定義的egg目錄放在最前面;

PYTHONPATH隨後(如果定義了PYTHONPATH環境變數的話);

pythonx.x.zip所在目錄隨後;

prefix plat_linux2 lib_tk lib_old這些目錄隨後;

lib-dynload的目錄隨後放進去;

*.pth定義的其他目錄放在最後;

預留了sitecustomize.py和usercustomize.py用戶用戶自定義一些行為。

這些path有兩個模塊構成:

getpath.c的caculate_path計算module_search_path、prefix、exec_prefix全局變數;

site.py用於將site-package目錄本身和該目錄下定義的*.pth文件中定義的目錄(包括egg,其實egg也是一個目錄,一個壓縮的目錄)放入sys.path中。

module_search_path、prefix、exec_prefix怎麼來的?

都是由caculate_path這個函數計算出來。

首先計算出python可執行文件所在的目錄,如果當前的可執行文件是一個軟鏈接,裡面會通過readlink找到最終的真正的可執行文件所在的目錄,這個目錄被賦值給變數argv0_path;

然後通過search_for_prefix從argv0_path一層層的上去找到包含landmark=lib/python2.7/os.py的目錄,並將該目錄(不包含os.py)賦值給prefix。

將prefix向上退兩層,然後加上python27.zip,將其賦值給局部變數zip_path。

同計算prefix相同的邏輯,計算exec_prefix,只不過這時候landmark變成了lib/python2.7/lib-dynload。並賦值給exec_prefix。(getpath.c的注釋中說道prefix放一些跨平台的代碼;而exec_prefix放平台先關的代碼或者二進位文件)。

然後就開始組合module_search_path了:

如果定義了PYTHONPATH,放進去;

zip_path放進去;

通過prefix+defpath(=:plat_linux2:lib_tk:lib_old)找到這些目錄的全路徑放進去,由於第一個是空的,所以會把prefix也放進去;

把exec_prefix放進去。

site-package怎麼放進去的?

site.py中,有個addsitedir函數,該函數將讀取site-package中的pth文件內容,並將該內容一行行的加入sys.path中,如果該行以import開頭,則執行。

而將egg放在sys.path的前面就是pth文件中,用import開頭來做的。

計算出來的三個全局變數什麼時候加入到sys.path中?

在pythonrun.c中的Py_InitializeEx函數中:

首先通過_PySys_Init初始化sys模塊,此時已經計算出了三個變數,並將prefix、exec_prefix賦值給sys模塊的prefix和exec_prefix;

後面有調用PySys_SetPath將module_search_path賦值給sys模塊的path;

在然後通過initsite初始化site.py模塊,由於該模塊里有main的調用,因此import site模塊會自動計算site-package相關環境,並進一步加入sys.path中。

dist-package、site-package有什麼區別?

dist-package可能存在兩個:

/usr/lib/pythonx.x/dist-packages。利用debian包管理器安裝的python第三方庫會放入這裡;

/usr/local/lib/pythonx.x/dist-packages。由於pip、easy_install這些工具也是用debian包管理安裝的,所以通過這些工具安裝的第三方庫放在這裡;

site-package只存在與自己源碼編譯的python版本中:

比如在我的電腦上由於用了默認路徑,就存在/usr/local/lib/pythonx.x/site-packages/。通過自己編譯的python安裝的第三方庫都放在該目錄中。

搞這些是因為做好兼容,防止第三方庫由於python版本不同而導致的不兼容。因此,如果你用系統自帶的python安裝了很多第三庫,然後又自己編譯了python,就要重新安裝這些第三方庫。可以通過一些技巧公共部分第三方庫(比如修改pth),但是不建議這樣搞,因此這樣做並不能保證兼容性。

如何修改sys.path?

修改syspath 有幾種方式:

直接加入sys.path列表中;

將目錄加入PYTHONPATH環境變數中,這種方式簡單粗暴,容易引起不可預知的問題,比如其他地方也用到了這個環境變數;

將第三方庫egg目錄或者第三放庫py目錄加入.pth中

自定義sitecustomize.py和usercustomize.py文件。

參考:

http://mikeboers.com/blog/2014/05/23/where-does-the-sys-path-start

https://stackoverflow.com/questions/9387928/whats-the-difference-between-dist-packages-and-site-packages


喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 LynnTech 的精彩文章:

TAG:LynnTech |