【问题标题】:Mix Python virtualenv packages with distro packages?将 Python virtualenv 包与发行包混合?
【发布时间】:2015-07-17 15:29:50
【问题描述】:

当您使用 Python virtualenv 但您希望通过发行版的包管理器安装某些包时,有什么好的方法来处理这种情况?

假设您需要 lxml,但因为您无法让 pip install lxml 在 Ubuntu 上工作。而且你真的不想在这上面浪费时间,所以你只需做一个apt-get install python-lxml。

现在,您可以使用--system-site-packages 创建一个virtaulenv,并可以访问系统范围内安装的预编译lxml。但是您还将拖入您不需要的所有其他系统范围的软件包!是的,会有相当多的包将通过sudo pip ... 或sudo apt-get python-... 安装在virtualenv 之外,所以没有“只需保持系统清洁并在virtualenvs 中安装所有可以安装的东西,这样@ 987654326@ 不会拖太多包” 不是我这里的解决方案。

那么,有没有办法只安装一些特定的系统站点包?

【问题讨论】:

  • 您能解释一下为什么拥有一个可以访问所有系统包的 virtualenv 会有问题吗?
  • @Andrzej 原来我对下面刚刚解释的 selurvedu 有点无知(“”在用户主目录中由 pip 安装的包比系统范围的包具有更高的优先级,因此,当进行导入。在 virtualenv 中,仅当使用 --system-site-packages 选项创建 virtualenv 时才会导入它们。通过 pip 在 vi​​rtualenv 中安装的包具有更高的优先级。”)。知道了这一点,我发现这在我的情况下,如果会的话,他的答案仍然成立......
  • 没错,我一直成功地将系统范围的包与本地安装的pip install --user和virtualenv结合起来。实现优先级的层次结构很重要。

标签: python ubuntu pip virtualenv


【解决方案1】:

我总是使用pip install --user packagename——它不需要 sudo。

如果您还没有pip,或者操作系统的pip 或操作系统的easy_install 无法正常工作,请先在用户的主目录中安装setuptools,然后将其easy_install 用于@ 987654328@.

$ wget https://bootstrap.pypa.io/ez_setup.py -O - | python3 - --user
$ easy_install-3.4 --user pip

另一方面,如果您决定在 virtualenv 中使用 pip,请不要使用 --user 选项,原因很明显。


按照您描述的方式进行操作

例如,我想导入 OS 中存在的模块 curl。

$ pip3 install --user virtualenv
$ python3 -m virtualenv myvenv
$ cd myvenv
$ source bin/activate
(myvenv)$ python3
>>> import curl
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ImportError: No module named curl

virtualenv 中没有这样的模块。只是为了确保我查看了 sys.path 中的内容。

>>> import sys
>>> sys.path
['',
'/home/username/myvenv/lib/python27.zip',
'/home/username/myvenv/lib/python2.7',
'/home/username/myvenv/lib/python2.7/lib-dynload',
'/usr/lib/python2.7', '/usr/lib/python2.7/plat-linux2',
'/home/username/myvenv/lib/python2.7/site-packages']

请注意,没有/usr/lib/python3.4/site-packages,正如您所希望的,但/usr/lib/python3.4 存在。如果这不适合您,请在创建 virtualenv 时使用 --always-copy 选项。

在接下来的步骤中,我创建了指向 curl 模块及其依赖项的符号链接。

>>> ^D # Press Control-D
(myvenv)$ ln -s /usr/lib/python3.4/site-packages/curl lib/python3.4/site-packages/

请注意,第二个参数(符号链接指向的文件或目录)中没有斜杠,但第三个参数(应创建符号链接的位置)中有一个斜杠。那是因为我在目录lib/python3.4/site-packages 的inside 创建了一个符号链接。如果没有尾部斜杠,它将尝试替换目录。

让我们检查一下是否有效。

(myvenv)$ python3
>>> import curl
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/username/myvenv/lib/python3.4/site-packages/curl/__init__.py", line 9, in <module>
    import sys, pycurl
ImportError: No module named 'pycurl'

不。 curl 取决于 pycurl。我们需要更深入。

>>> ^D
(myvenv)$ ls -1 /usr/lib/python3.4/site-packages/pycurl*
/usr/lib/python3.4/site-packages/pycurl-7.19.3.1-py3.4.egg-info
/usr/lib/python3.4/site-packages/pycurl.cpython-34m.so
(myvenv)$ ln -s /usr/lib/python3.4/site-packages/pycurl-7.19.3.1-py3.4.egg-info lib/python3.4/site-packages/
(myvenv)$ ln -s /usr/lib/python3.4/site-packages/pycurl.cpython-34m.so lib/python3.4/site-packages/
(myvenv)$ python3
>>> import curl
>>> curl
<module 'curl' from '/home/username/myvenv/lib/python3.4/site-packages/curl/__init__.py'>

终于。

这是你需要的吗?


就我个人而言,我强烈反对你这样做,因为首先,这是一种变态。

此外,我怀疑这种方法适用于所有情况。依赖的深度可能很可怕。

其次,我认为没有理由避免 --system-site-packages 在我被认可的所有情况下都像一个魅力。

pip 安装在用户主目录下的包优先级高于系统范围的包,因此在执行import 时优先使用。 在 virtualenv 中,只有在使用 --system-site-packages 选项创建 virtualenv 时才会导入它们。 在 virtualenv 中由pip 安装的包具有更高的优先级。

老实说,我写这个答案只是为了问,为什么你想搞砸这一切而不是让pip 工作。我还不能在 SO 上写 cmets,所以这就是我写完整答案的原因。 :)

但您也会拖入所有其他您不需要的系统范围的软件包!

不,你不会的。只有在执行import 时才将模块加载到内存中。如果您的意思是该软件包将出现在 virtualenv 中——再一次,它不会出现。如果您查看了 myvenv/lib/python3.4/site-packages/ 的内部,您会发现里面只有两个包 - pip 和 setuptools(尽管后者被分成几个目录)。 virtualenv 中的 Python 解释器只是像普通解释器一样加载系统范围的模块。


附:上面的代码也适用于 Python 2.7。只需将pip3 替换为pip2,将python3 替换为python2,将3.4 替换为2.7,等等。

附言除了符号链接,您可以将模块及其依赖项复制到 virtualenv 到相应的目录中。这在使用 --always-copy 时很有意义,这样您的 virtualenv 就变得可移植了。

P.P.P.S.如果您决定使用带有--system-site-packages 和pip 的virtualenv,并且假设您希望requests 包比/usr/lib 中已安装的包更新,请使用pip install -I,如here 所述。

【讨论】:

  • 谢谢。这部分特别有帮助和启发性:“在用户主目录中由 pip 安装的包比系统范围的包具有更高的优先级,因此,在导入时它们首先被采用。在 virtualenv 中,只有在 virtualenv 使用创建时才会导入它们 - -system-site-packages 选项。通过 pip 在 vi​​rtualenv 中安装的软件包具有更高的优先级。” :) 我现在选择--system-site-packages,在其他情况下,当我有更多时间或愿意让事情变得更清洁时,我会想办法让 pip 也适用于更“特殊”的包。 .
猜你喜欢
  • 2013-01-17
  • 2017-12-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-06-01
  • 2023-03-16
  • 1970-01-01
  • 2014-10-31
相关资源
最近更新 更多