依 site 所言, python 預設會載入 site.py 來載入 sys.path 的主要內容 (但可用 python -S 取消這點)。這就是 virtualenv 切入的點, 它利用 python 找到 site.py 的規則, 讓 python 載入 virtualenv 修改過的 site.py, 於是就能掌控之後的載入內容 (如不要載入 global site-packages)。
詳細的的規則參照 site, 這裡以 Ubuntu + python2.5 為例。執行 /X/bin/python 後, 若存在目錄 /X/lib/python2.5/ 的話, sys.prefix 會存成 /X (我試的結果是, 若找不到 /X/lib/python2.5/, 會存成 /usr), sys.path 的內容依序如下:
- 被執行的 python script 的位置。比方執行 python /home/fcamel/main.py, 就是 /home/fcamel
- sys.prefix + "/lib/python2.5/site.py"
- site.py 載入的東東, 懶得看到底做了那些事
- ...
- shell 內設的環境變數 PYTHONPATH
- ...
剩下一些細節之後有機會再來弄清楚。從 site.py 裡沒看到 PYTHONPATH, 而 python 原始碼裡有類似的東西 ( Modules/getpath.c )。
回歸正題, 建立 virtualenv 時, virtualenv 會產生一個目錄, 其中包含一個 shell script 。執行 script 後會換掉 PATH, 讓使用者執行 python 時會先執行到 virtualenv 放的 python。這個 python 和系統裝的 python 一模一樣, 目的只是要換掉 sys.prefix, 藉此控制 site.py 載入的路徑。比方說執行到 /home/fcamel/my_env/bin/python, 若它發現能找到 /home/fcamel/my_env/lib/python2.5/, 就會把 sys.prefix 設成 /home/fcamel/my_env, 於是就能載入自己放的 site.py 了 (即 /home/fcamel/my_env/lib/python2.5/site.py )。
沒有留言:
張貼留言