Python环境演变之路:从Pyvenv到uv

702 阅读2分钟

Version 1: Pyvenv

安装pyenv

github.com/pyenv/pyenv…

pyenv用于多版本Python管理器

可能会报错,缺少lmza,安装xz模块,brew install xz

brew install pyenv

配置环境

echo 'export PYENV_ROOT="$HOME/.pyenv"' >> ~/.zprofile
echo 'export PATH="$PYENV_ROOT/shims:$PATH"' >> ~/.zprofile
echo 'eval "$(pyenv init --path)"' >> ~/.zprofile
echo 'eval "$(pyenv init -)"' >> ~/.zprofile

安装python3.13.1,并设为全局

pyenv install --list
pyenv install 3.13.1
pyenv global 3.13.1

安装pyenv-virtualenv

brew install pyenv-virtualenv

配置环境

echo 'eval "$(pyenv virtualenv-init -)"' >> ~/.zprofile

创建虚拟环境

创建后会在~/.pyenv/versions下创建一个文件夹

pyenv virtualenv python版本 虚拟环境名称
pyenv virtualenv 3.13.1 virtual-env-3.13.1

激活&失效环境

pyenv activate 虚拟环境名称
pyenv activate virtual-env-3.13.1

pyenv deactivate

在当前目录或者父目录下执行pyenv local,就可以进入目录自动切换到Python环境,但是在目录下再去切换环境,可能会失效,解决办法,清除本地配置。

pyenv local用处:对于某些项目可以通过pyenv local来配置好,不用每次都需要重新制定环境。

pyenv local --unset

pyenv将所有的环境保存在 ~/.pyvenv/versions,类似于全局环境管理,环境不跟随项目。如果有很多项目需要维护,比较麻烦,最好结合pyenv local一起使用。

Version 2: Pyvenv to UV

参考文档:

UV安装

之前使用pyvenv,现在想切换到uv,因为uv对虚拟环境管理更为友好。

brew install uv

uv官方文档

常用命令

# 查看python版本
uv python list
# 安装指定python版本
uv python install python版本号

# 根据uv初始化项目
uv init 项目名

# 使用uv创建虚拟环境,会生成.venv文件夹,类似于python3 -m venv .venv
uv venv
# 基于project.toml同步项目环境
uv sync

# 项目添加包名,会添加到project.toml
uv add 包名
# 项目删除包名,会从project.toml中删除
uv remove 包名
# 仅在开发时安装包名
uv add 包名 --dev

direnv结合uv

基于uv实现的环境管理后,环境管理创建,但是每次都需要source .venv/bin/activate​才能激活环境。能不能实现进入项目目录,自动激活环境?在看了一些哔哩哔哩课程以及搜索后,看到了direnv这个库,基于direnv可以实现进入环境自动激活环境,退出目录环境失效。

direnv安装

brew install direnv
echo 'eval "$(direnv hook zsh)"' >> ~/.zshrc

direnv配置 layout_uv函数

layout_uv() {
    if [[ -d ".venv" ]]; then
        VIRTUAL_ENV="$(pwd)/.venv"
    fi

    if [[ -f ".python-version" ]]; then
        PYTHON_VERSION=$(cat .python-version)
        echo $PYTHON_VERSION
    fi

    if [[ -z $VIRTUAL_ENV || ! -d $VIRTUAL_ENV ]]; then
        log_status "No virtual environment exists. Executing `uv venv` to create one."
        uv venv
        VIRTUAL_ENV="$(pwd)/.venv"
    fi

  

    PATH_add "$VIRTUAL_ENV/bin"
    export UV_ACTIVE=1  # or VENV_ACTIVE=1
    export VIRTUAL_ENV

    # Activate the virtual environment
    . $VIRTUAL_ENV/bin/activate
}

.zshrc配置venv()函数

venv() {
    local venv_name
    local dir_name=$(basename "$PWD")

    # If there are no arguments or the last argument starts with a dash, use dir_name
    if [ $# -eq 0 ] || [[ "${!#}" == -* ]]; then
         ="$dir_name"
    else
        venv_name="${!#}"
        set -- "${@:1:$#-1}"
    fi

    # Check if .envrc already exists
    if [ -f .envrc ]; then
        echo "Error: .envrc already exists" >&2
        return 1
    fi

    # Create venv using uv with all passed arguments
    if ! uv venv --seed --prompt "$@" "$venv_name"; then
        echo "Error: Failed to create venv" >&2
        return 1
    fi

    # Create .envrc
    echo "layout uv" > .envrc

    # Append to ~/.projects
    echo "${venv_name} = ${PWD}" >> ~/.projects

    # Allow direnv to immediately activate the virtual environment
    direnv allow
}

shell显示默认环境

配置完后,根据which python命令,发现环境确实被激活了,但是并没有显示当前环境,需要设置终端现实环境。

具体操作如下:

PS1设置

# Add direnv-activated venv to prompt
show_virtual_env() {
  if [[ -n "$VIRTUAL_ENV_PROMPT" && -n "$DIRENV_DIR" ]]; then
    echo "$(basename $VIRTUAL_ENV_PROMPT)"
  fi
}
PS1='$(show_virtual_env)'$PS1