16

我创建了一个python3虚拟环境(明确避免符号链接,使用--copies):

» python3 -m venv --without-pip --copies venv

这是我现在完整的虚拟环境:

» tree venv/
venv/
├── bin
│   ├── activate
│   ├── activate.csh
│   ├── activate.fish
│   ├── python
│   └── python3
├── include
├── lib
│   └── python3.4
│       └── site-packages
├── lib64 -> lib
└── pyvenv.cfg

我禁用PYTHONPATH, 以确保没有任何东西从外部泄漏:

» PYTHONPATH=""

激活venv:

» source venv/bin/activate

验证activate没有污染我的PYTHONPATH

» echo $PYTHONPATH

(空白,正如预期的那样)

我正在使用正确的python:

» which python
/foo/bar/venv/bin/python

但系统模块仍在被访问:

» python 
Python 3.4.3 (default, Oct 14 2015, 20:28:29) 
[GCC 4.8.4] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import unittest
>>> print(unittest)
<module 'unittest' from '/usr/lib/python3.4/unittest/__init__.py'>
>>> 

我预计该import unittest语句会失败,因为虚拟环境没有这样的模块。

我想知道:

  • 为什么在 virtualenv 中访问系统包?
  • 如何创建一个完全独立的虚拟环境?
4

2 回答 2

9

如果我没记错的话,核心系统包是符号链接的,所以它们是相同的文件(部分是为了减小 virtualenv 的大小)。

默认不包含该site-packages目录,因此它不会访问已安装的 3rd 方库。

如果你想真正隔离和自包含的虚拟环境,你最好看看docker

Virtualenv 实际上更像是一种轻量级的方式,可以为不同的应用程序管理不同的 3rd 方安装包。

编辑:

看起来--always-copy并不总是复制所有文件:

virtualenv 不会从 lib/python 目录复制所有 .py 文件

深入研究源代码,看起来有一小部分模块被认为是“必需的”,这些是被复制的:

https://github.com/pypa/virtualenv/blob/ac4ea65b14270caeac56b1e1e64c56928037ebe2/virtualenv.py#L116

编辑2:

您可以看到旧的 python 目录仍然出现在sys.path, 但在 virtualenv 本身的目录之后:

>>> import sys
>>> sys.path
['', '/home/john/venv/lib/python2.7', 
'/home/john/venv/lib/python2.7/plat-linux2', 
'/home/john/venv/lib/python2.7/lib-tk',
'/home/john/venv/lib/python2.7/lib-old', 
'/home/john/venv/lib/python2.7/lib-dynload', '/usr/lib/python2.7',
'/usr/lib/python2.7/plat-linux2',
'/usr/lib/python2.7/lib-tk',
'/home/john/venv/local/lib/python2.7/site-packages',
'/home/john/venv/lib/python2.7/site-packages']
于 2016-01-27T10:58:44.693 回答
0

你可以在旧的 Linux 上从源代码构建 python;那么python将是完全独立的并且能够在许多Linux上运行。

在参考链接中,它是在容器环境中的 centos 5 上构建 python 3.6 的步骤详细信息。输出可用于许多 Linux,如 debian 10、centos 6、7、8、photon 3、alpine,...

  • readline-devel: 启用 python 命令行历史
  • sqlite-devel: 启用 sqlite 支持
  • expat-devel: 启用 xmltree 支持
  • bzip2-devel: 启用 bzip2 支持
  • 从源代码编译 SSL 以避免动态库链接
  • 如果是更高版本的 python,也许你还需要编译更高版本的 gcc 以获得完整的 C++11 和更高的支持
  • 编译后,您需要从 pypi.python.org 下载 setuptools 和 pip 并python setup.py install为这个独立的 python 准备好 pip。

参考:https ://github.com/stallpool/track-network-traffic#mitmproxy-for-manylinux

于 2021-11-10T01:56:26.487 回答