可移植的python環境

pwolp發表於2022-03-21

建立可移植的python環境

工作時使用的系統不聯網,而且自帶的python環境庫不完整,每次幹活都心累,所以想要做一個可移植的精簡版的python環境。

開始前的準備:

  • Ubuntu18.04
  • python原始碼
  • virtualenv

這裡首先裝Linux版本的,Windows版本的之後補上。

python原始碼安裝

在官網下載python原始碼,這裡使用的是python3.7.12,可以在這裡下載。使用的python版本影響不大。

需要的依賴包:gcc,zlib,zlib-devel,openssl-devel,readline,readline-devel

注意:

  1. 在Ubuntu中zlib叫zlib1g,zlib-devel叫zlib1g-dev,所以安裝時需要:
    sudo apt-get install zlib1g
    sudo apt-get install zlib1g-dev
  2. 在Ubuntu中openssl-devel需要分開裝:
    sudo apt-get install openssl
    sudo apt-get install libssl-dev

下載之後,解壓,

root@yyy:~# tar zxvf Python-3.7.12.tgz

然後進入解壓後的檔案進行編譯,

root@yyy:~# cd Python-3.7.12
root@yyy:~/Python-3.7.12# ./configure --prefix=/root/python37
...
...

等一會,結束之後就可以編譯安裝了,

root@yyy:~/Python-3.7.12# make && make install
...
...

再等一會,安裝成功,安裝路徑為/root/python37

安裝virtualenv

安裝virtualenv可以直接使用pip install virtualenv

建立虛擬環境

這裡使用的是virtualenv20.13.3,通過幫助檢視使用方法,這裡介紹一些使用的選項。

這裡吐槽一下,中文網際網路上的文章都是來回抄的,而且內容不加驗證,一大堆垃圾,沒有一點用處。

virtual引數

  • -p或者--python,指定python直譯器,通過這個引數可以指定需要的python版本;
  • --system-site-packages,讓虛擬環境可以訪問系統環境的庫,預設False,這裡不做修改就行,之後會將直接使用虛擬環境的庫;
  • --copies,將一些需要的東西複製到虛擬環境,預設為False,我們是需要複製的;
  • --prompt,指定虛擬環境的字首,這個隨意就行。

還有一些為了精簡環境,刪除了一些功能,按需修改:

  • --no-vcs-ignore,不知道什麼用處就不需要了;
  • --no-download,不下載最新的pip/setuptoos/wheel,預設為True
  • --no-pip,不安裝pip,預設為False
  • --no-setuptools,不安裝setuptools,預設為False
  • --no-wheel,不安裝wheel,預設為False
  • --no-periodic-update,不要週期更新,預設為False

最後建立虛擬環境:

root@yyy:~# virtualenv --python=/root/python37/bin/python3.7 --no-vcs-ignore  --copies --system-site-packages --no-download --no-pip --no-setuptools --no-periodic-update --prompt venv venv

執行成功之後,就會有一個venv的資料夾,這就是虛擬環境了。

root@yyy:~# ls
python37    venv
root@yyy:~# source venv/bin/activate
(venv) root@yyy:~# deactivate
root@yyy:~# 

可以看到(venv)就是虛擬環境的標誌,這個通過--prompt引數修改。

接下來就是重頭戲,讓虛擬環境成為獨立的環境。

虛擬環境修改

首先看一下虛擬環境的檔案結構,

root@yyy:~# ls venv/
bin    lib    pyvenv.cfg

後來裝py2的環境時發現另外有一個include資料夾,但是不影響,主要修改的是上面的三個。

修改bin

bin中包括的是啟動相關的檔案,包括啟動指令碼和直譯器。

直譯器包括三個python*檔案,只需要留下來一個就行了,如果留下python,虛擬環境呼叫就使用python,如果留下python3.7,就用python3.7呼叫。

啟動指令碼只需要activate就行了,其他格式的指令碼是用於不同環境的啟動,按需保留。

所以最後剩下的就只有activatepython這兩個檔案。


開啟activate檔案,在第47行,VIRTUAL_ENV='/root/venv',這裡指定的是虛擬環境的絕對路徑,但是為了可移植性需要修改一下這裡,我修改為

PWD=$(pwd)
VIRTUAL_ENV="$PWD/venv"

這樣修改啟動的話只能是在venv資料夾的同一個目錄中啟動,因為pwd獲取的是當前路徑,而不是檔案的路徑

因為實在是不知道怎麼獲取當前檔案的絕對路徑了,找了各種方法,如果有好的方法,測試之後告訴我,一定要測試一下,我也試了好多種方法。

這樣bin就修改好了。

修改lib

lib儲存的是庫相關的東西,由於現在建立的虛擬環境都是直接使用指定直譯器的庫,這個可以用sys.path測試一下。我們這裡直接將已安裝好的python的庫複製到這裡,但是不要複製site-packages資料夾,由於庫很多,所以可以適當的刪減。

修改pyvenv.cfg

上面修改lib之後,並不能直接使用,所以需要修改pyvenv.cfg檔案,我是這樣修改的,

home = 
implementation = CPython
version_info = 3.7.12.final.0
virtualenv = 20.13.3
include-system-site-packages = false
base-prefix = 
base-exec-prefix = 
base-executable = bin/python3.7

上面沒有指定目錄的預設當前目錄。

總結

到這裡就可以了,測試一下,

root@yyy:~# source venv/bin/activate
(venv) root@yyy:~# python --version
Python 3.7.12
(venv) root@yyy:~# python
Python 3.7.12 (default, Mar 18 2022, 19:42:43)
[GCC 7.5.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import sys
>>> sys.path
['', '/root/venv/lib/python37.zip', '/root/venv/lib/python3.7', '/root/venv/lib/python3.7/lib-dynload', '/root/venv/lib/python3.7/site-packages']
>>> ^Z
(venv) root@yyy:~# deactivate
root@yyy:~# 

打包後在別的資料夾測試,然後在別的系統上測試,我在下面的系統測試過:

  • ubuntu 18.04
  • kali2022
  • kali
  • 一個不知道是什麼版本的Linux,沒聯網,什麼都沒有,使用py37的虛擬環境是提示libc.so.6缺少GLIBC25GLIBC26,這個沒有什麼解決辦法,系統也沒有聯網。

總的來說還是挺好用的。

相關文章