python環境部署(二) —— conda環境遷移

前言

《python環境部署(一) —— pip依賴遷移》中,我介紹了純粹使用pip安裝python模塊的情況下如何進行依賴的遷移。沒有看過的讀者建議先看一看。
本文,我將繼續介紹如何在使用conda的情況下進行環境的遷移。

同樣不可靠的方法

conda與pip一樣提供了導出依賴的方法:

conda list -e > requirements.txt

文件格式如下:

<package>=<version>=<build>

與pip導出的文件略有不同。
在待部署機器上,可以使用以下命令安裝依賴以恢復依賴環境:

conda create --name <env> --file requirements.txt

此外,由於conda提供了虛擬環境導出的功能,可以按以下步驟複製一個環境:
首先,用以下命令導出一個environment.yml文件:

conda env export -f environment.yml

然後使用以下命令重建虛擬環境:

conda env create -f environment.yml

與pip相同,以上兩種方法也存在一些問題。下面我仔細解釋。

同樣的問題:找不到匹配的包

使用requirements.txt安裝同樣存在找不到包的問題(PackagesNotFoundError):
conda找不到適配的包
造成這個現象,有與pip同樣的原因——鏡像源的更新,還有一個特殊的情況,那就是上圖中無法匹配到的那些包,如果背後是pypi_0的,說明是通過pip安裝的,這些包在使用requirements.txt文件安裝時是不會得到conda支持的,因爲他們是通過pip安裝的。換言之,通過conda list導出的requirements.txt文件既包括conda安裝的包,也包括pip安裝的包,這些通過pip安裝的包無法通過conda來安裝。這其中原因包括:
1)命名規則的不同,
2)開發者數量的不對等(因此有些包conda上確實沒有),
3)編譯系統的差異導致版本號不對應,
4)並不是通過pypi安裝的包等。
這些能夠造成確實無法找到適配的包,但是更關鍵的還是多出了那pypi_0的後綴,這就導致了實際上很多包應該是匹配的,但是卻搜索不到,因爲找不到pypi_0這個Build名。

對待由於鏡像源更新造成的找不到包的問題,不重要的包可以做升級,重要的包則需要單獨考慮了。
批量更新conda的包可以使用:

conda update --all

在我更新conda安裝的包並重新導出requirements.txt(先排除非pypi_0結尾的那些包)文件進行安裝後,有63個通過pip安裝的包無法匹配到:
在這裏插入圖片描述
在VSCode中,用空字符替換“=pypi_0”:
在這裏插入圖片描述
再進行一次安裝嘗試,則只剩下14個再conda源中確實無法搜索到的包了。
在這裏插入圖片描述
而如果我們使用conda env導出的environment.yml文件,則可以避開這個問題。在這個文件中,分別記錄了使用pip安裝的包和從conda的源中安裝的包:
在這裏插入圖片描述
conda在處理這些pip安裝的包時,將會轉而採用pip來處理:
在這裏插入圖片描述
所以我給出的建議是,要解決這個問題,就直接不使用conda list導出requirements.txt這個方法,仍然使用pip導出requirements.txt文件,按照《python環境部署(一) —— pip依賴遷移》中所述的方法進行處理。對於conda安裝的那一部分,導出environm.yml文件,刪除其中pip部分,並使用下面介紹的方法處理。

離線部署

《python環境部署(一) —— pip依賴遷移》中已經明確了,實現離線部署纔是最終的目的。

對於conda,看到一些教程介紹一個簡單粗暴的方法,就是一股腦把虛擬環境目錄複製下來(在conda主目錄的envs目錄下),然後拷貝到待部署機器上。這麼做有一個非常糟糕的問題,就是prefix絕對目錄的問題。在環境目錄下用grep搜索一下,就可以發現,有大量文件內嵌了絕對目錄,這在部署機器上是無法正常工作的,除非你能做到兩臺機器完全對等,連用戶名都一樣,這顯然是不現實的。

可以用sed命令替換prefix,或者使用conda-pack這個模塊:

# 安裝(測試機器和待部署機器上都需要)
conda install -c conda-forge conda-pack
# 測試機器上導出環境
conda pack -n my_env -o out_name.tar.gz
# 待部署機器上導入環境
mkdir -p my_env
tar -xzvf out_name.tar.gz -C my_env
# 待部署機器上激活環境(這條命令會將my_env/bin添加到path環境變量,之後方可支持conda activate)
source my_env/bin/activate
# 待部署機器上替換prefix
conda-unpack

跨平臺部署

對於跨平臺部署,同樣建議在真實的機器或者虛擬機中測試好以後再按以上離線部署方法去部署。這裏介紹一下如何減少其中的工作量。
environment.yml中dependencies格式如下:

- <package>=<version>=<build>

其實package和version對於不同平臺來說基本都是一樣的,區別就在於build。conda根據不同平臺構建二進制包時,就會產生有不同的build。據此,如果刪除了build這個字段後,就可以匹配絕大多數的包。
在VSCode中用以下正則表達式匹配這個字段並用空字符替換:
在這裏插入圖片描述
這樣一來,就只會有少數包無法正常被搜索到,再進行個別的安裝即可。

關於其他工具的說明

(1)conda create --clone
conda create --clone命令亦可用於環境複製/遷移,但實測中卻發現仍然會在源上搜索包進行安裝,也無法限制其不去搜索源(開啓–offline亦不生效),我不確定這是不是bug,總之我不用它:

conda create --offline --name [dest_venv_name]  --clone [src_venv_name] 

(2)搭建本地源
conda也可以搭建本地源來實現離線部署,但遺憾的是,我在conda 4.5.12上嘗試的很多命令都無法生效(例如–offline、–download-only),我在help信息中確認過,語法上並沒有問題,使我對其失去了興趣,沒有再折騰下去。所以,就到這裏吧。有興趣的就自己瞭解下吧。
https://blog.csdn.net/haveanybody/article/details/84025759

(2)conda-bundle
conda也有一些人編寫了類似於pip-bundle的工具,叫做conda-bundle,感興趣的可以看看。
https://github.com/minrk/conda-bundle

參考文獻

https://conda.github.io/conda-pack/
https://blog.csdn.net/haveanybody/article/details/84025759
https://github.com/minrk/conda-bundle

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章