virtualenv 可重定位 - 这真的能做到吗

18 投票
2 回答
24173 浏览
提问于 2025-04-17 00:08

我一直在寻找答案,但没找到。 我有一个虚拟环境的文件夹,还有一个项目文件夹,里面有一个req.txt文件。 当我运行pip -r req.txt时,它会从github(源代码)和pypi安装一些应用程序。 从pypi安装的那些应用程序在虚拟环境中运行得很好,但从github安装的应用程序在site-packages中的链接仍然指向旧的目录位置。

有没有人遇到过这种情况?有没有什么快速的解决办法? 另外,relocatable没有遵循最初在虚拟环境中使用的--no-site-packages标志。一旦你移动了虚拟环境并重新激活它,系统的site-packages中的所有内容都会变得可见。文档中提到这种行为是事实,所以我在想有没有什么快速的解决办法?

2 个回答

12

不,首先,'--relocatable' 这个选项并不会更新 'virtualenv/bin/activate' 这个脚本。虽然你可以按照zeekay的建议重新运行虚拟环境的设置来修复这个问题,但这仍然无法导入那些放在 'virtualenv/src' 里的 'pip -e git ...' 安装包,所以你得手动重新运行这些 pip 安装。

随着我作为开发者的经验增加,我现在尽量避免使用额外的依赖和抽象层,因为这些往往会成为出错的地方。

所以现在我不再使用 pip 的可编辑安装(-e),如果需要的话,我会手动把代码库克隆到 'project/src/' 而不是 'project/virtualenv/src',并在启动我的项目之前加载下面的 auto_prep_pythonpath.py 脚本(我在我的 django.wsgi 脚本中引用它)。

顺便提一下,我会在任何放在 'project/src' 的修改过的包名后加上 'tailored',这样我就不用担心向后兼容性的问题,并且我会把所有源代码放在代码管理下,因为在线代码库可能会出问题。

希望这对你有帮助。

"""
Prepares python path to include additional project/src/<APP> in PYTHONPATH - This file gets automatically loaded by projects __init__.py

This script lives in 'project/src/django-project/auto_prep_pythonpath.py', modify 
'SOURCE_ROOT' if you place it somewhere else.
"""
import logging
import os
import sys
SOURCE_ROOT = os.path.dirname(os.path.abspath(__file__)).replace('\\','/') # the replacements are when on windows
SOURCE_ROOT = os.path.join(SOURCE_ROOT, '../').replace('\\','/') 
SOURCE_ROOT = os.path.normpath(SOURCE_ROOT)

logger = logging.getLogger(__name__)

logger.info("Adding packages in 'src/*' required by project to PYTHONPATH.")
dirlist_arr = os.listdir(SOURCE_ROOT)
while dirlist_arr:
    item_path = os.path.join(SOURCE_ROOT, dirlist_arr.pop()).replace('\\','/') # replace dashes is for win based file system
    if os.path.isdir(item_path):
        if not item_path in sys.path:
            sys.path.insert(0, item_path) # we use insert to take precedence over any global paths - minimizes import conflict surprises
        logger.debug("Path '%s' added."  % item_path)
14

正如文档中所说,--relocatable是一个实验性的选项,所以你遇到困难也不奇怪。话说回来,你有没有在安装新包后重新运行--relocatable?如果你是通过-e从github安装的包,那可能会有问题,因为这种方式并不是直接安装到site-packages,而是创建了一个指向它的链接。作为--relocatable的替代方案,你通常可以删除与虚拟环境相关的文件,然后在原地重新创建它(我在切换平台时做过几次)。

撰写回答