Python venv虛擬環(huán)境跨設(shè)備遷移的實(shí)現(xiàn)
背景
我們通常會(huì)遇到想簡(jiǎn)易搬遷一臺(tái)設(shè)備的python開發(fā)環(huán)境到另外一臺(tái)設(shè)備的情況,但可能我們另一臺(tái)設(shè)備本身的python環(huán)境包括系統(tǒng)環(huán)境是不可控的,這里我遇到的是從centos7搬遷python開發(fā)環(huán)境到centos6,centos7自帶的python環(huán)境為2.7.5版本且一些依賴的文件庫(kù)也是適配2.7.5版本及以上的,導(dǎo)致我們把環(huán)境搬遷到centos6的默認(rèn)python2.6.6環(huán)境下時(shí),產(chǎn)生了非常多的報(bào)錯(cuò),以下文檔內(nèi)容記錄我遇到的報(bào)錯(cuò)及解決方式,并提供一種較為完美的方式輕量級(jí)的解決環(huán)境移植問題。
python加載lib庫(kù)的順序
環(huán)境
制作python 虛擬環(huán)境設(shè)備:
- 系統(tǒng)版本:centos 7
- python版本:python2.7.5
移植的目標(biāo)設(shè)備:
- 系統(tǒng)版本:centos 6
- python版本:python2.6.6
詳細(xì)操作
安裝virtualenv
[centos 7] # pip install virtualenv
創(chuàng)建python venv環(huán)境
[centos 7] # mkdir -p /opt/python_venv_test [centos 7] # virtualenv -p /usr/bin/python2.7 --copies /opt/python_venv_test
--copies的參數(shù)意思為盡量不要為/opt/python_venv_test的文件創(chuàng)建軟鏈接,如果不指定該參數(shù),我們可以看到/opt/python_venv_test目錄有些文件就是這樣的:
[centos 7] # ll /opt/python_venv_test/lib64/python2.7/* lrwxrwxrwx 1 root root ? 32 Apr 26 20:24 /opt/python_venv_test/lib64/python2.7/lib-dynload -> /usr/lib64/python2.7/lib-dynload lrwxrwxrwx 1 root root ? 26 Apr 26 20:24 /opt/python_venv_test/lib64/python2.7/os.py -> /usr/lib64/python2.7/os.py lrwxrwxrwx 1 root root ? 27 Apr 26 20:24 /opt/python_venv_test/lib64/python2.7/os.pyc -> /usr/lib64/python2.7/os.pyc -rw-r--r-- 1 root root 6978 Apr 26 20:24 /opt/python_venv_test/lib64/python2.7/site.py /opt/python_venv_test/lib64/python2.7/config: total 0 lrwxrwxrwx 1 root root 36 Apr 26 20:24 Makefile -> /usr/lib64/python2.7/config/Makefile /opt/python_venv_test/lib64/python2.7/site-packages: total 0
可以看到很多文件直接是做了軟鏈接到原python 環(huán)境中的lib庫(kù)中的文件,如果這個(gè)時(shí)候咱們把他打包移植到另外的設(shè)備,這些文件就全部都會(huì)被清空,所以一定要加--copies這個(gè)參數(shù)。加了--copies參數(shù)之后是這樣的:
[centos 7] # ll -d /opt/python_venv_test/lib64/python2.7/* drwxr-xr-x 2 root root 4096 Apr 26 20:31 /opt/python_venv_test/lib64/python2.7/config drwxr-xr-x 2 root root 4096 Apr 26 20:31 /opt/python_venv_test/lib64/python2.7/lib-dynload -rw-r--r-- 1 root root 25769 Apr 26 20:31 /opt/python_venv_test/lib64/python2.7/os.py -rw-r--r-- 1 root root 25557 Apr 26 20:31 /opt/python_venv_test/lib64/python2.7/os.pyc drwxr-xr-x 2 root root 4096 Apr 26 20:31 /opt/python_venv_test/lib64/python2.7/site-packages -rw-r--r-- 1 root root 6978 Apr 26 20:31 /opt/python_venv_test/lib64/python2.7/site.py
可以看到?jīng)]有軟鏈接了,那么我們這個(gè)環(huán)境就是完全獨(dú)立的,這時(shí)候我們的python venv環(huán)境就已經(jīng)生成了。
打包依賴的glibc庫(kù)
我們的python環(huán)境為python2.7.5版本,比較推薦的是使用glibc-2.17版本,下載地址為:glibc下載地址 ,里面有各個(gè)版本的glibc文件。
為什么這里要打包依賴的glibc庫(kù)呢?
我把虛擬環(huán)境目錄移植到目標(biāo)的centos6機(jī)器上測(cè)試了一下,如果上面的這些庫(kù)文件在新的設(shè)備上沒有,那么就會(huì)報(bào)錯(cuò),這里我遇到的報(bào)錯(cuò)就是:
/bin/python: error while loading shared libraries: libpython2.7.so.1.0: cannot open shared object file: No such file or directory
./bin/python: /lib64/libc.so.6: version `GLIBC_2.14' not found (required by /usr/lib64/libpython2.7.so.1.0)
這兩個(gè)報(bào)錯(cuò)都是很有可能會(huì)命中的,提示我們?nèi)鄙賻?kù)文件,沒有辦法運(yùn)行python binary。
那么到底缺少哪些庫(kù)文件呢?我們可以通過readelf -d /opt/python_venv_test/bin/python 命令檢查python binary的依賴文件:
[centos 7] # readelf -d /opt/python_venv_test/bin/python Dynamic section at offset 0xdd8 contains 29 entries: ? Tag ? ? ? ?Type ? ? ? ? ? ? ? ? ? ? ? ? Name/Value ?0x0000000000000001 (NEEDED) ? ? ? ? ? ? Shared library: [libpython2.7.so.1.0] ?0x0000000000000001 (NEEDED) ? ? ? ? ? ? Shared library: [libpthread.so.0] ?0x0000000000000001 (NEEDED) ? ? ? ? ? ? Shared library: [libdl.so.2] ?0x0000000000000001 (NEEDED) ? ? ? ? ? ? Shared library: [libutil.so.1] ?0x0000000000000001 (NEEDED) ? ? ? ? ? ? Shared library: [libm.so.6] ?0x0000000000000001 (NEEDED) ? ? ? ? ? ? Shared library: [libc.so.6] ?0x000000000000000c (INIT) ? ? ? ? ? ? ? 0x4005e0 ?0x000000000000000d (FINI) ? ? ? ? ? ? ? 0x4007a4 ?0x0000000000000019 (INIT_ARRAY) ? ? ? ? 0x600dc0 ?0x000000000000001b (INIT_ARRAYSZ) ? ? ? 8 (bytes) ?0x000000000000001a (FINI_ARRAY) ? ? ? ? 0x600dc8 ?0x000000000000001c (FINI_ARRAYSZ) ? ? ? 8 (bytes) ?0x000000006ffffef5 (GNU_HASH) ? ? ? ? ? 0x400298 ?0x0000000000000005 (STRTAB) ? ? ? ? ? ? 0x400478 ?0x0000000000000006 (SYMTAB) ? ? ? ? ? ? 0x4002f8 ?0x000000000000000a (STRSZ) ? ? ? ? ? ? ?218 (bytes) ?0x000000000000000b (SYMENT) ? ? ? ? ? ? 24 (bytes) ?0x0000000000000015 (DEBUG) ? ? ? ? ? ? ?0x0 ?0x0000000000000003 (PLTGOT) ? ? ? ? ? ? 0x601000 ?0x0000000000000002 (PLTRELSZ) ? ? ? ? ? 48 (bytes) ?0x0000000000000014 (PLTREL) ? ? ? ? ? ? RELA ?0x0000000000000017 (JMPREL) ? ? ? ? ? ? 0x4005b0 ?0x0000000000000007 (RELA) ? ? ? ? ? ? ? 0x400598 ?0x0000000000000008 (RELASZ) ? ? ? ? ? ? 24 (bytes) ?0x0000000000000009 (RELAENT) ? ? ? ? ? ?24 (bytes) ?0x000000006ffffffe (VERNEED) ? ? ? ? ? ?0x400578 ?0x000000006fffffff (VERNEEDNUM) ? ? ? ? 1 ?0x000000006ffffff0 (VERSYM) ? ? ? ? ? ? 0x400552 ?0x0000000000000000 (NULL) ? ? ? ? ? ? ? 0x0
我們可以在兩臺(tái)機(jī)器上查看一下到底有沒有庫(kù)文件,以及庫(kù)文件產(chǎn)出自哪個(gè)rpm包:
目標(biāo) centos 6機(jī)器沒有找到libpython2.7.so.1.0庫(kù)文件, 而/lib64/libc.so.6文件版本較低,沒有達(dá)到glibc-2.14版本:
[centos 6] # ?whereis libpython2.7.so.1.0 libpython2.7.so.1: [centos 6] # whereis /lib64/libc.so.6 libc.so: /lib/libc.so.6 /lib64/libc.so.6 /usr/lib64/libc.so [centos 6] # rpm -qf /lib64/libc.so.6 glibc-2.12-1.80.el6.x86_64
我們回到centos 7機(jī)器看看,可以看到有l(wèi)ibpython2.7.so.1.0這個(gè)文件,而且/usr/lib64/libc.so.6的版本也大于glibc-2.14版本。
[centos 7] # whereis libpython2.7.so.1.0 libpython2.7.so.1: /usr/lib64/libpython2.7.so.1.0 [centos 7] # ?rpm -qf /usr/lib64/libpython2.7.so.1.0 python-libs-2.7.5-68.el7.x86_64 [centos 7] # ?whereis /lib64/libc.so.6 libc.so: /usr/lib/libc.so.6 /usr/lib64/libc.so /usr/lib64/libc.so.6 [centos 7] # ?rpm -qf /usr/lib64/libc.so.6 glibc-devel-2.17-260.el7_6.3.x86_64
好了, 我們回歸正題,我們現(xiàn)在要解決上面這些問題。
首先,在centos 7機(jī)器上,下載及安裝glibc-2.17:
[centos 7] # wget http://ftp.gnu.org/gnu/glibc/glibc-2.17.tar.xz -O /tmp/ [centos 7] # cd /tmp/; tar xf glibc-2.17.tar.xz; cd /tmp/glibc-2.17 [centos 7] # mkdir build; cd build [centos 7] # ../configure --prefix=/opt/python_venv_test/glibc-217 [centos 7] # make -j4 [centos 7] # make install
以上操作完成后,我們就可以在/opt/python_venv_test/glibc-217目錄下看到glibc-2.17的所有文件都在里面了。然后我們把發(fā)現(xiàn)的不屬于glibc但又需要的庫(kù)文件libpython2.7.so.1.0移植進(jìn)來glibc-2.17的lib目錄里:
[centos 7] # cp -ar /usr/lib64/libpython2.7.so.1.0 /opt/python_venv_test/glibc-217/lib/
除了glibc這個(gè)基礎(chǔ)庫(kù),還需要python本身的基礎(chǔ)庫(kù),是運(yùn)行binary python時(shí)需要加載的模塊,比如os等,這個(gè)庫(kù)一般是在系統(tǒng)的/usr/lib64/python2.7/目錄,我們把它移植到我們的虛擬環(huán)境目錄下(這個(gè)地方如果我們本地的/usr/lib64/python2.7 過大,可以考慮起一個(gè)可運(yùn)行干凈的python環(huán)境centos 7虛擬機(jī),把它的/usr/lib64/python2.7拷貝過來,這樣就能保證它是最小的包量):
[centos 7] # rm -rf /opt/python_venv_test/lib64/python2.7 [centos 7] # cp -ar /usr/lib64/python2.7 /opt/python_venv_test/lib64/python2.7
如果上面這個(gè)操作你沒有做,可能就會(huì)遇到這樣的報(bào)錯(cuò):
[centos 7] # ./bin/python
Could not find platform independent libraries <prefix>
Could not find platform dependent libraries <exec_prefix>
Consider setting $PYTHONHOME to <prefix>[:<exec_prefix>]
ImportError: No module named site
當(dāng)你把$PYTHONHOME設(shè)置完成后,或者會(huì)遇到這樣的報(bào)錯(cuò)(總之就是找不到基礎(chǔ)庫(kù)文件):
[centos 7] # ./bin/python
Traceback (most recent call last):
File "/home/zhaoqiang09/bsc_python_venv.b/lib64/python2.7/site.py", line 190, in <module>
main()
File "/home/zhaoqiang09/bsc_python_venv.b/lib64/python2.7/site.py", line 18, in main
rewrite_standard_library_sys_path()
File "/home/zhaoqiang09/bsc_python_venv.b/lib64/python2.7/site.py", line 97, in rewrite_standard_library_sys_path
import os
ImportError: No module named os
改寫環(huán)境加載文件/opt/python_venv_test/pyvenv.cfg,這樣我們就不需要依賴移植后目標(biāo)centos 6系統(tǒng)本身的lib庫(kù)了,以免造成版本沖突:
home = /opt/python_venv_test/ implementation = CPython version_info = 2.7.5.final.0 virtualenv = 20.13.0 include-system-site-packages = false base-prefix = /opt/python_venv_test/ base-exec-prefix = /usr base-executable = /opt/python_venv_test/bin/python
我們還得改寫一下/opt/python_venv_test/bin/activate 文件,這個(gè)文件是我們?cè)谝浦埠竽繕?biāo)centos 6系統(tǒng)加載python虛擬環(huán)境的入口,我們?cè)谶@里面加一條對(duì)LD_LIBRARY_PATH環(huán)境變量的局部重寫(紅色字體部分,第一條是為了退出環(huán)境變量時(shí),下掉alias的綁定,第二條是開始加載activate環(huán)境時(shí)對(duì)LD_LIBRARY_PATH環(huán)境變量的局部重寫):·
·········· deactivate () { ? ? unalias python >/dev/null 2>&1 ? ? unset -f pydoc >/dev/null 2>&1 || true ············· # Make sure to unalias pydoc if it's already there alias pydoc 2>/dev/null >/dev/null && unalias pydoc || true alias python="${VIRTUAL_ENV}/glibc-217/lib/ld-2.17.so --library-path ${VIRTUAL_ENV}/glibc-217/lib:/lib64 ${VIRTUAL_ENV}/bin/python" ·················
然后,我們就可以打包了:
[centos 7] # cd /opt/ [centos 7] # tar -czf python_venv_test.tar.gz python_venv_test
移植包到目標(biāo)Centos 6系統(tǒng)上執(zhí)行
首先在centos 7 系統(tǒng)上我們scp壓縮包到目標(biāo)機(jī)器
[centos 7] # cd /opt/ [centos 7] # scp python_venv_test.tar.gz root@centos_6:/opt/python_venv_test.tar.gz
然后我們?cè)赾entos 6上解壓壓縮包:
[centos 6] # cd /opt/ [centos 6] # tar xf python_venv_test.tar.gz
這時(shí)候就可以虛擬環(huán)境目錄運(yùn)行python了
[centos 6] # cd /opt/python_venv_test [centos 6] # souce bin/bin/activate [centos 6] # python Python 2.7.5 (default, Apr 11 2018, 07:36:10) [GCC 4.8.5 20150623 (Red Hat 4.8.5-28)] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>>
我們要擴(kuò)充一些第三方擴(kuò)展包
回到centos7機(jī)器
搬遷新增的flask、requests、psutil等第三方庫(kù)
我們還是先回到我們的虛擬環(huán)境目錄/opt/python_venv_test下面,先使用bin目錄下的pip安裝flask
# ./bin/pip install flask requests psutil
打壓縮包,并拷貝壓縮包到centos 6目標(biāo)系統(tǒng)上
cd /opt/ tar -czf python_venv_test.tar.gz python_venv_test/ [centos 7] # scp python_venv_test.tar.gz root@centos_6:/opt/python_venv_test.tar.gz
回到centos6 機(jī)器上,解壓縮包,并運(yùn)行python看看有沒有什么問題
cd /opt/python_venv_test/ # source bin/activate # python Python 2.7.5 (default, Apr 11 2018, 07:36:10) [GCC 4.8.5 20150623 (Red Hat 4.8.5-28)] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>> import flask bash: /opt/bsc_python_venv/glibc-217/lib/libssl.so.10: No such file or directory
報(bào)錯(cuò)顯示缺少libssl.so.10文件,我們看看這個(gè)文件分別在兩臺(tái)測(cè)試機(jī)的哪里:
centos 6機(jī)器情況:
# whereis libssl.so.10 ld-2.17:
centos 7機(jī)器情況,并且要確定的是它不是一個(gè)軟鏈接:
# whereis libssl.so.10 libssl.so: /usr/lib64/libssl.so.10 /usr/lib64/libssl.so # ll -d /usr/lib64/libssl.so.10 lrwxrwxrwx 1 root root 16 Jan 21 ?2021 /usr/lib64/libssl.so.10 -> libssl.so.1.0.2k # ll -d /usr/lib64/libssl.so.1.0.2k -rwxr-xr-x 1 root root 470360 Mar 12 ?2019 /usr/lib64/libssl.so.1.0.2k
我們?cè)侔裞entos7 的 /usr/lib64/libssl.so.1.0.2k 這個(gè)文件給放到虛擬環(huán)境glibc-217目錄,然后做成壓縮包,傳到centos6機(jī)器上,再來試試
# cp -ar /usr/lib64/libssl.so.1.0.2k /opt/python_venv_test/glibc-217/lib/libssl.so.10 # cd /opt/ # tar -czf python_venv_test.tar.gz python_venv_test/ [centos 7] # scp python_venv_test.tar.gz root@centos_6:/opt/python_venv_test.tar.gz
我們?cè)僭赾entos 6的機(jī)器上把原來的文件刪除,解壓縮,再試試import flask、requests、psutil這三個(gè)庫(kù)文件,就不會(huì)再報(bào)剛才那個(gè)錯(cuò)了:
cd /opt/python_venv_test/ # source bin/activate # python Python 2.7.5 (default, Apr 11 2018, 07:36:10) [GCC 4.8.5 20150623 (Red Hat 4.8.5-28)] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>> import flask >>> import requests >>> import psutil
結(jié)束!
本文設(shè)計(jì)的內(nèi)容較多,如果有一些細(xì)節(jié)不太懂的地方,建議自行搜索,再回來反復(fù)查看本文檔。
到此這篇關(guān)于Python venv虛擬環(huán)境跨設(shè)備遷移的實(shí)現(xiàn)的文章就介紹到這了,更多相關(guān)Python venv遷移內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
pyCharm中python對(duì)象的自動(dòng)提示方式
這篇文章主要介紹了pyCharm中python對(duì)象的自動(dòng)提示方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-09-09python基于socketserver實(shí)現(xiàn)并發(fā),驗(yàn)證客戶端的合法性
TCP協(xié)議的socket一次只能和一個(gè)客戶端通信, 而socketsever可以時(shí)間和多個(gè)客戶端通信。本文將講解socketserver的具體使用2021-05-05python中關(guān)于CIFAR10數(shù)據(jù)集的使用
這篇文章主要介紹了python中關(guān)于CIFAR10數(shù)據(jù)集的使用方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-02-02Python Pygame實(shí)戰(zhàn)之實(shí)現(xiàn)經(jīng)營(yíng)類游戲夢(mèng)想小鎮(zhèn)代碼版
作為一名模擬經(jīng)營(yíng)類游戲的發(fā)燒友,各種農(nóng)場(chǎng)類、醫(yī)院類、鐵路類的游戲玩兒了很多年。今天用代碼給大家打造一款夢(mèng)想小鎮(zhèn)游戲,希望大家喜歡啦2022-12-12