如何让virtualenv在Ubuntu上使用dist-packages?

25
我知道,如果在创建新的虚拟环境时没有传递--no-site-packages参数,virtualenv将会把位于/usr/local/lib/python2.7/site-packages(Python 2.7)中的包与新创建的虚拟环境连接起来。在Ubuntu 12.04 LTS上,我有三个位置可以安装Python 2.7的软件包(使用默认的Ubuntu提供的Python 2.7安装方式):
  1. /usr/lib/python2.7/dist-packages:这里安装了我全局的ipython、scipy、numpy、matplotlib等包,如果它们不是通过scipy stack提供的,则单独安装这些包及其依赖关系将非常困难和耗时。
  2. /usr/local/lib/python2.7/site-packages:这是空的,除非我从源代码安装软件包,否则我认为它会一直保持为空。
  3. /usr/local/lib/python2.7/dist-packages:这里有非常重要的天文本地包,特别是那些与PyRAF、STScI等相关的包,如果它们不是通过虚拟环境提供的,则单独安装这些包及其依赖关系将非常困难和耗时。
请注意,像/usr/lib/python2.7/site-packages这样的全局目录在我的系统上不存在。此外,我的ipython、scipy等全局安装让我能够在不必每次激活虚拟环境的情况下即时使用这些包。
当然,现在我想使用virtualenv在用户主目录下创建一个虚拟环境,并为我的未来项目激活该环境。但是,我希望在创建时该虚拟环境可以链接/复制上述列表中(1)和(3)位置中的所有软件包。主要原因是我不想为此(以及可能的其他)虚拟环境重新安装ipython、scipy、astro-packages等软件包(如果可能的话)。
以下是我的问题:
  • 有没有办法告诉virtualenv在未来创建的虚拟环境中链接/复制这两个dist-packages目录中的软件包?
  • 当我最终更新这两个dist-packages目录中全局安装的scipy,ipython等时,这是否也会更新/更改我的虚拟环境使用的软件包(它们最初是在virtualenv创建期间获取的)?
  • 如果我在Ubuntu上从源代码安装软件包,它会放在/usr/local/lib/python2.7/dist-packages还是/usr/local/lib/python2.7/site-packages中?
  • 提前感谢您的帮助!

    5个回答

    18

    这可能是使用 PYTHONPATH 的合理用法 - 它是一个环境变量,virtualenv 不会影响到它,与环境变量 PATH 使用相同的语法,在bash中使用 PYTHONPATH=/usr/lib/python2.7/dist-packages:/usr/local/lib/python2.7/dist-packages 在.bashrc或类似的文件中。如果你选择了这种路径,

    1. 你不必告诉你的虚拟环境任何关于这个的信息,它也不会试图去更改它。

    2. 不需要重新链接,

    3. 安装的包将仍然安装在原来的目录下 (pip install 在我的Ubuntu上始终使用 /usr/local/lib/python2.7/dist-packages/ ) 如果你把它们安装在虚拟环境之外。如果你在虚拟环境中安装它们(在激活虚拟环境时),当然它们将被放置在虚拟环境中。


    4
    非常好用,谢谢!另一种方法是创建一个 .pth 文件,在其中每一行都是要添加到默认 sys.path 的路径,并将该文件放置在虚拟环境的 site-packages 目录中,例如,在 /home/userX/envY/lib/python2.7/site-packages 中创建 dist-packages.pth。我目前选择了后一种方法,因为它更明确地解释了为什么这个特定的虚拟环境可以访问全局的 dist-packages 目录,而不是通过 .bashrc 中的 "全局" PYTHONPATH 环境变量。 - quantumflash
    2
    啊,那也不错。有时我会在虚拟环境中的激活脚本中添加一些东西,你可以在其中设置和取消PYTHONPATH,但由于.pth文件可用,这可能更好。不过,那是放置其他类似东西的好地方。 - Thomas
    这个很有效。在按照这个答案的建议设置PYTHONPATH之前,我无法从虚拟环境中使用pip安装numpy。 - Will
    1
    使用.pth文件可以很好地进行配置管理,因为在安装过程中将预先准备好的文件复制到指定位置非常简单。 - James Moore
    我使用的是Ubuntu 14.04,/usr/lib/python2.7目录的所有者是root。我正在尝试使用virtualenv(或任何必要的方法)在Jenkins上运行Python unittest测试。我的Jenkins系统用户无法访问这些目录。我不想将我的Jenkins用户添加到root组中。我在这里做错了什么? - siliconsmiley

    8

    我正在了解virtualenv,但似乎有一种比之前提到的更简单的方法。

    1. 自从virtualenv 1.7后,默认行为已经变成了--no-site-packages。因此,如果您使用的是Ubuntu发行版中的调整过的virtualenv,则只需要使用--system-site-packages标志就可以将dist-packages加入您的路径中。(这个回答这个回答给出了一些有用的历史记录)。我进行了测试,它确实有效。

      $ virtualenv --system-site-packages .

    2. 我同意Thomas的观点-在virtualenv中看到dist-packages更新的效果不需要任何操作。

    3. 通过测试python setup.py install,还是会将软件包安装到dist-packages中(正如Thomas所说)。你可以通过构建自己的Python来改变这一点,但这有点极端。


    4

    PYTHONPATH 对我很有用。

    vim ~/.bashrc
    

    请在下面添加这一行:
    export PYTHONPATH=$PYTHONPATH:/usr/lib/python2.7/dist-packages:/usr/local/lib/python2.7/dist-packages
    source ~/.bashrc
    

    如果 /usr/lib/python2.7/dist-packages 是由 root 拥有,而你正在使用非 root 系统帐户,该怎么办? - siliconsmiley

    4
    在目录site-packages中创建文件dist.pth,在文件dist.path中写入以下内容:../dist-packages

    enter image description here

    现在请停用并激活您的虚拟环境,这样就可以了。

    2
    您想要实现的目标是将特定文件夹(dist-packages)添加到Python搜索路径中。以下是几种选择:
    1. 使用路径配置(.pth)文件,条目将被附加到系统路径。
    2. 修改PYTHONPATH(其中的条目将添加到系统路径开头)。
    3. 直接从您的Python脚本修改sys.path,即追加所需文件夹。
    我认为对于这个特定案例(启用全局dist-packages文件夹),第三个选项更好,因为第一个选项需要为每个virtualenv创建.pth文件(还需要一些外部shell脚本?)。在分发软件包时很容易忘记它。第二个选项需要运行时设置(添加环境变量),这也很容易被忽略。
    只有第三个选项不需要任何配置或运行时前提条件,并且可以在没有问题的情况下分发(当然是在同类型的系统上)。
    您可以使用如下函数:
    def enable_global_distpackages():
        import sys
        sys.path.append('/usr/lib/python2.7/dist-packages')
        sys.path.append('/usr/local/lib/python2.7/dist-packages')
    

    然后在您的包的__init__.py文件中:

    enable_global_distpackages()
    

    网页内容由stack overflow 提供, 点击上面的
    可以查看英文原文,
    原文链接