我总是使用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 所述。