virtualenv制作免安裝python虛擬環(huán)境

背景

  • 針對離線環(huán)境存在python版本不匹配涉枫,安裝三方庫緩慢或無外網(wǎng)的情況下,需要制作可移植的解釋器及其附帶的庫文件。
  • 由于sys.path是在安裝時設(shè)置(見下圖),直接壓縮安裝的python解釋器及其lib,include文件必然導(dǎo)致不兼容捶箱。
  • conda雖然內(nèi)置python解釋器但同樣需要安裝,不夠輕便
#sys.py
base_exec_prefix = 'C:\\ProgramData\\Anaconda3'

base_prefix = 'C:\\ProgramData\\Anaconda3'

byteorder = 'little'

copyright = 'Copyright (c) 2001-2019 Python Software Foundation.\nAll Rights Reserved.\n\nCopyright (c) 2000 BeOpen.com.\nAll Rights Reserved.\n\nCopyright (c) 1995-2001 Corporation for National Research Initiatives.\nAll Rights Reserved.\n\nCopyright (c) 1991-1995 Stichting Mathematisch Centrum, Amsterdam.\nAll Rights Reserved.'

dllhandle = 140724640546816

dont_write_bytecode = True

executable = 'C:\\ProgramData\\Anaconda3\\python.exe'

exec_prefix = 'C:\\ProgramData\\Anaconda3'

解決方案

使用virtualenv制作虛擬環(huán)境动漾,將原解釋器中l(wèi)ib丁屎、include與site-packages等不依賴路徑文件替換,并修改若干啟動項旱眯。

virtualenv用于制作虛擬環(huán)境晨川,python3.3后的標(biāo)準(zhǔn)庫中venv集成了virtualenv一些關(guān)鍵功能,具體區(qū)別:

virtualenv is a tool to create isolated Python environments.Since Python 3.3, a subset of it has been integrated into the standard library under the venv module. The venv module does not offer all features of this library, to name just a few more prominent:

  • is slower (by not having the app-data seed method),
  • is not as extendable,
  • cannot create virtual environments for arbitrarily installed python versions (and automatically discover these),
  • is not upgrade-able via pip,
  • does not have as rich programmatic API (describe virtual environments without creating them).

virtualenv命令選項

usage: virtualenv [--version] [--with-traceback] [-v | -q] [--discovery {builtin}] [-p py] [--creator {builtin,cpython2-posix}] [--seeder {app-data,pip}] [--no-seed] [--activators comma_separated_list] [--clear] [--system-site-packages]
                  [--symlinks | --copies] [--download | --no-download] [--extra-search-dir d [d ...]] [--pip version] [--setuptools version] [--wheel version] [--no-pip] [--no-setuptools] [--no-wheel] [--clear-app-data] [--symlink-app-data]
                  [--prompt prompt] [-h]
                  dest

optional arguments:
  --version                        display the version of the virtualenv package and it's location, then exit
  --with-traceback                 on failure also display the stacktrace internals of virtualenv (default: False)
  -h, --help                       show this help message and exit

verbosity:
  verbosity = verbose - quiet, default INFO, mapping => CRITICAL=0, ERROR=1, WARNING=2, INFO=3, DEBUG=4, NOTSET=5

  -v, --verbose                    increase verbosity (default: 2)
  -q, --quiet                      decrease verbosity (default: 0)

discovery:
  discover and provide a target interpreter

  --discovery {builtin}            interpreter discovery method (default: builtin)
  -p py, --python py               target interpreter for which to create a virtual (either absolute path or identifier string) (default: /usr/bin/python)

creator:
  options for creator builtin

  --creator {builtin,cpython2-posix}
                                   create environment via (builtin = cpython2-posix) (default: builtin)
  dest                             directory to create virtualenv at
  --clear                          remove the destination directory if exist before starting (will overwrite files otherwise) (default: False)
  --system-site-packages           give the virtual environment access to the system site-packages dir (default: False)
  --symlinks                       try to use symlinks rather than copies, when symlinks are not the default for the platform (default: True)
  --copies, --always-copy          try to use copies rather than symlinks, even when symlinks are the default for the platform (default: False)

seeder:
  options for seeder app-data

  --seeder {app-data,pip}          seed packages install method (default: app-data)
  --no-seed, --without-pip         do not install seed packages (default: False)
  --download                       pass to enable download of the latest pip/setuptools/wheel from PyPI (default: False)
  --no-download, --never-download  pass to disable download of the latest pip/setuptools/wheel from PyPI (default: True)
  --extra-search-dir d [d ...]     a path containing wheels the seeder may also use beside bundled (can be set 1+ times) (default: [])
  --pip version                    pip version to install, bundle for bundled (default: latest)
  --setuptools version             setuptools version to install, bundle for bundled (default: latest)
  --wheel version                  wheel version to install, bundle for bundled (default: latest)
  --no-pip                         do not install pip (default: False)
  --no-setuptools                  do not install setuptools (default: False)
  --no-wheel                       do not install wheel (default: False)
  --clear-app-data                 clear the app data folder of seed images (/root/.local/share/virtualenv/seed-v1) (default: False)
  --symlink-app-data               symlink the python packages from the app-data folder (requires seed pip>=19.3) (default: False)

activators:
  options for activation scripts

  --activators comma_separated_list
                                   activators to generate - default is all supported (default: bash,cshell,fish,powershell,python)
  --prompt prompt                  provides an alternative prompt prefix for this environment (default: None)

操作步驟

1. pip install virtualenv

2. virtualenv venv -p 解釋器路徑 --system-site-packages --copies

執(zhí)行命令生成venv文件夾删豺,集成了python的虛擬環(huán)境共虑。

具體參數(shù)說明見virtualenv命令選項,特別說明下要選擇--copies呀页,默認(rèn)的--symlinks會創(chuàng)建引用鏈接妈拌,移植會導(dǎo)致鏈接失效不可用

選擇--symlinks后的venv/lib/python3.6

(root) [root@host-192-169-100-115 python3.6]# pwd
/home/venv/lib/python3.6
(root) [root@host-192-169-100-115 python3.6]# ls -al
lrwxrwxrwx.  1 root root    58 Mar  5 00:57 abc.py -> /home/runtime/lib/python3.6/abc.py
lrwxrwxrwx.  1 root root    61 Mar  5 00:57 base64.py -> /home/runtime/lib/python3.6/base64.py
lrwxrwxrwx.  1 root root    61 Mar  5 00:57 bisect.py -> /home/runtime/lib/python3.6/bisect.py

3.拷貝原有解釋器的lib(lib64)、include等文件(site-packages含在lib內(nèi))復(fù)制到venv一級目錄下

virtualenv的說明中有一段:

Created python virtual environments are usually not self-contained. A complete python packaging is usually made up of thousand of files, so it’s not efficient to install the entire python again into a new folder. Instead virtual environments are mere shells, that contain little within itself, and borrow most from the system python (this is what you installed, when you installed python itself). This does mean that if you upgrade your system python your virtual environments might break, so watch out. The upside of this referring to the system python is that creating virtual environments can be fast.

提到拷貝完整文件對于虛擬環(huán)境并沒有意義蓬蝶,會借用系統(tǒng)解釋器的部分組件供炎,故新版本的virtualenv已經(jīng)不含lib庫渴逻,并且脫離lib庫的python無法運(yùn)行。

本需求需要一個完整的python音诫,故手動拷貝惨奕。(如果virtualenv有選項更好,可惜并沒有找到)

venv目錄:

[root@host-192-169-100-115 venv]# ll
total 12
drwxr-xr-x. 2 root root 4096 Mar  5 01:02 bin
drwxr-xr-x. 2 root root 4096 Mar  5 00:57 include
drwxr-xr-x. 3 root root 4096 Mar  5 00:57 lib
drwxr-xr-x. 3 root root 4096 Mar  5 00:57 pyenv.cfg

4.刪除venv中目錄下的pyenv.cfg文件1

若無該文件可以不關(guān)注竭钝。

5.修改bin目錄下執(zhí)行腳本的絕對路徑

當(dāng)前有兩類文件存在絕對路徑:

  1. bin目錄下其他可執(zhí)行python工具梨撞,開頭解釋器為固定解釋器

以pip舉例:

#!/usr/bin/python3.6

# -*- coding: utf-8 -*-
import re
import sys

from pip import main

if __name__ == '__main__':
    sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0])
    sys.exit(main())

修改前:

#!/usr/bin/python3.6

修改后:

#!/usr/bin/env python3.6
  1. 用于啟動虛擬環(huán)境的bin/activate文件,其中venv的目錄為絕對路徑

修改前:

VIRTUAL_ENV="/home/venv"

修改后:

CUR_BIN_DIR=$(cd $(dirname ${BASH_SOURCE:-$0});pwd)
VIRTUAL_ENV="$(dirname $CUR_BIN_DIR)"

驗證步驟

  1. 切換任意目錄讀取activate中命令(source venv所在文件夾/venv/bin/activate)
[root@SDN-4416-1 venv]# source /home/runtime/venv/bin/activate
  1. 檢查python命令索引
(venv) [root@SDN-4416-1 venv]# which python
/home/runtime/venv/bin/python
  1. 進(jìn)入python控制器臺檢查標(biāo)準(zhǔn)庫和三方庫路徑非借用
(venv) [root@SDN-4416-1 venv]# python
Python 3.7.4 (default, Aug 13 2019, 20:35:49)
[GCC 7.3.0] :: Anaconda, Inc. on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import os
>>> os.__file__
'/home/runtime/venv/lib/python3.7/os.py'
>>> import requests
>>> requests.__file__
'/home/runtime/venv/lib/python3.7/site-packages/requests/__init__.py'
>>>

延伸閱讀

1.刪除venv中目錄下的pyenv.cfg文件香罐?

文件內(nèi)容:

[root@SDN-4416-1 venv]# cat pyvenv.cfg
home = /usr
implementation = CPython
version_info = 2.7.5.final.0
virtualenv = 20.0.4
include-system-site-packages = true
base-prefix = /usr
base-exec-prefix = /usr
base-executable = /usr/bin/python

為了解釋這個操作的原因卧波,先引出兩個問題:

  1. 虛擬環(huán)境下的python可執(zhí)行文件與系統(tǒng)默認(rèn)的有什么不同呢?
  2. Python又是如何找到虛擬環(huán)境下的第三方庫的呢庇茫?

事實(shí)上港粱,上面提到的python可執(zhí)行文件之間并沒有什么不同,但是它們所在的位置至關(guān)重要旦签。在Python啟動的時候查坪,它會獲取自身所在的路徑。然后這一路徑(bin的上一級)被設(shè)置到sys.prefix和sys.exec_prefix之中宁炫。

sys.prefix
A string giving the site-specific directory prefix where the platform independent Python files are installed; by default, this is the string '/usr/local'. This can be set at build time with the --prefix argument to the configure script. The main collection of Python library modules is installed in the directory prefix/lib/pythonX.Y while the platform independent header files (all except pyconfig.h) are stored in prefix/include/pythonX.Y, where X.Y is the version number of Python, for example 3.2.
Note If a virtual environment is in effect, this value will be changed in site.py to point to the virtual environment. The value for the Python installation will still be available, via base_prefix.
在搜索第三方的site-packages時偿曙,搜索目錄是sys.prefix所指向的路徑下的lib/pythonX.X/site-packages/,其中X.X是Python的版本羔巢。

假設(shè)python文件所在路徑為/Users/michaelherman/python-virtual-environments/env/bin望忆,因此sys.prefix會被設(shè)為/Users/michaelherman/python-virtual-environments/env,從而site-packages的路徑就變成了/Users/michaelherman/python-virtual-environments/env/lib/pythonX.X/site-packages竿秆。最后启摄,這一路徑被存儲在sys.path數(shù)組中,其中包含著所有包的引用來源幽钢。

詳見:Python虛擬環(huán)境詳解

再來歉备,關(guān)于pyenv.cfg有這樣的解釋:

PEP-405 Python Virtual Environments

When the Python binary is executed, it attempts to determine its prefix (which it stores in sys.prefix), which is then used to find the standard library and other key files, and by the site module to determine the location of the site-package directories. Currently the prefix is found (assuming PYTHONHOME is not set) by first walking up the filesystem tree looking for a marker file (os.py) that signifies the presence of the standard library, and if none is found, falling back to the build-time prefix hardcoded in the binary.

This PEP proposes to add a new first step to this search. If a pyvenv.cfg file is found either adjacent to the Python executable or one directory above it (if the executable is a symlink, it is not dereferenced), this file is scanned for lines of the form key = value. If a home key is found, this signifies that the Python binary belongs to a virtual environment, and the value of the home key is the directory containing the Python executable used to create this virtual environment.

In this case, prefix-finding continues as normal using the value of the home key as the effective Python binary location, which finds the prefix of the base installation. sys.base_prefix is set to this value, while sys.prefix is set to the directory containing pyvenv.cfg.

(If pyvenv.cfg is not found or does not contain the home key, prefix-finding continues normally, and sys.prefix will be equal to sys.base_prefix.)

Also, sys.base_exec_prefix is added, and handled similarly with regard to sys.exec_prefix. (sys.exec_prefix is the equivalent of sys.prefix, but for platform-specific files; by default it has the same value as sys.prefix.)
The site and sysconfig standard-library modules are modified such that the standard library and header files are found relative to sys.base_prefix / sys.base_exec_prefix, while site-package directories ("purelib" and "platlib", in sysconfig terms) are still found relative to sys.prefix / sys.exec_prefix.

Thus, a Python virtual environment in its simplest form would consist of nothing more than a copy or symlink of the Python binary accompanied by a pyvenv.cfg file and a site-packages directory.

同樣可以通過標(biāo)準(zhǔn)site.py找到對pyenv.cfg文件的引用:

#site.py
If a file named "pyvenv.cfg" exists one directory above sys.executable,
sys.prefix and sys.exec_prefix are set to that directory and
it is also checked for site-packages (sys.base_prefix and
sys.base_exec_prefix will always be the "real" prefixes of the Python
installation). If "pyvenv.cfg" (a bootstrap configuration file) contains
the key "include-system-site-packages" set to anything other than "false"
(case-insensitive), the system-level prefixes will still also be
searched for site-packages; otherwise they won't.

也就是說sys.prefix和sys.exec_prefix被設(shè)置好后,pyenv.cfg存在時虛擬環(huán)境時會繼續(xù)替換為文件中的前綴,在本需求中沒有必要搅吁,故刪去威创。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市谎懦,隨后出現(xiàn)的幾起案子肚豺,更是在濱河造成了極大的恐慌,老刑警劉巖界拦,帶你破解...
    沈念sama閱讀 212,718評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件吸申,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)截碴,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,683評論 3 385
  • 文/潘曉璐 我一進(jìn)店門梳侨,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人日丹,你說我怎么就攤上這事走哺。” “怎么了哲虾?”我有些...
    開封第一講書人閱讀 158,207評論 0 348
  • 文/不壞的土叔 我叫張陵丙躏,是天一觀的道長。 經(jīng)常有香客問我束凑,道長晒旅,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,755評論 1 284
  • 正文 為了忘掉前任汪诉,我火速辦了婚禮废恋,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘扒寄。我一直安慰自己鱼鼓,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,862評論 6 386
  • 文/花漫 我一把揭開白布旗们。 她就那樣靜靜地躺著蚓哩,像睡著了一般构灸。 火紅的嫁衣襯著肌膚如雪上渴。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 50,050評論 1 291
  • 那天喜颁,我揣著相機(jī)與錄音稠氮,去河邊找鬼。 笑死半开,一個胖子當(dāng)著我的面吹牛隔披,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播寂拆,決...
    沈念sama閱讀 39,136評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼奢米,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了纠永?” 一聲冷哼從身側(cè)響起鬓长,我...
    開封第一講書人閱讀 37,882評論 0 268
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎尝江,沒想到半個月后涉波,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,330評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,651評論 2 327
  • 正文 我和宋清朗相戀三年啤覆,在試婚紗的時候發(fā)現(xiàn)自己被綠了苍日。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,789評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡窗声,死狀恐怖相恃,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情笨觅,我是刑警寧澤豆茫,帶...
    沈念sama閱讀 34,477評論 4 333
  • 正文 年R本政府宣布,位于F島的核電站屋摇,受9級特大地震影響揩魂,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜炮温,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,135評論 3 317
  • 文/蒙蒙 一火脉、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧柒啤,春花似錦倦挂、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,864評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至涛癌,卻和暖如春犯戏,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背拳话。 一陣腳步聲響...
    開封第一講書人閱讀 32,099評論 1 267
  • 我被黑心中介騙來泰國打工先匪, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人弃衍。 一個月前我還...
    沈念sama閱讀 46,598評論 2 362
  • 正文 我出身青樓呀非,卻偏偏與公主長得像,于是被迫代替她去往敵國和親镜盯。 傳聞我的和親對象是個殘疾皇子岸裙,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,697評論 2 351

推薦閱讀更多精彩內(nèi)容