使用Python virtualenv 处理这种情况的好方法是什么,但是您想要通过发行版的软件包管理器安装一些软件包?
我们假设您需要 lxml ,但因为您无法让pip install lxml
在Ubuntu上工作。而且你真的不想浪费时间在这上面,所以你只需要apt-get install python-lxml
。
现在,您可以使用--system-site-packages
创建virtaulenv,并且现在可以访问系统范围内安装的预编译 lxml 。但是,您也会拖入您不需要的所有其他系统级软件包!是的,将会有很多软件包安装在virtualenv之外,通过sudo pip ...
或sudo apt-get python-...
,所以没有"只需保持系统清洁并安装所有内容可以在virtualenvs中,以便--system-site-packages
不会用它拖动太多的包#34; 不是我在这里的解决方案。
那么,有没有办法安装某些特定的系统网站包?
答案 0 :(得分:1)
我总是使用pip install --user packagename
- 它不需要sudo。
如果您还没有pip
,或者操作系统的pip
或操作系统的easy_install
无法正常工作,请先在用户的主目录中安装setuptools
,然后然后将easy_install
用于pip
。
$ wget https://bootstrap.pypa.io/ez_setup.py -O - | python3 - --user
$ easy_install-3.4 --user pip
另一方面,如果您决定在virtualenv中使用pip
,请不要使用--user
选项。
例如,我想导入操作系统中存在的模块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
中创建了 符号链接。如果没有尾部斜杠,它会尝试替换目录。
让我们检查一下是否有效。
(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时才会导入它们。
由pip
在virtualenv中安装的软件包具有更高的优先级。
老实说,我写这个答案只是为了问,为什么你想要搞砸所有这些而不是让pip
工作。我还不能写关于SO的评论,所以这就是为什么我写了一个完整的答案。 :)
不,你不会。只有在执行但是你也会拖入你不需要的所有其他系统范围的包!
import
时才将模块加载到内存中。如果你的意思是包装将出现在virtualenv中 - 再一次,它不会。如果您查看了myvenv/lib/python3.4/site-packages/
内部,您会看到内部只有两个包 - pip
和setuptools
(后者分为几个目录)。 virtualenv中的Python解释器只是像普通的解释器一样加载系统范围的模块。
P.S。上面的代码也适用于Python 2.7。只需将pip3
替换为pip2
,python3
替换为python2
,3.4
替换为2.7
等。
P.P.S。您可以将带有依赖项的模块复制到virtualenv到相应的目录,而不是符号链接。使用--always-copy
时这是有道理的,这样你的virtualenv就变得可移植了。
P.P.P.S。如果您决定将virtualenv与--system-site-packages
和pip
一起使用,并且,比方说,您希望requests
包比/usr/lib
中已安装的包更新,请使用{{ 1}},如here所述。