环境变量配置
环境变量(Environment Variable)是操作系统传递给进程的键值对(Key-Value Pair),Python 解释器会读取其中一批特定变量来改变自身行为。正确配置环境变量,能让你在任意目录使用 python 与 pip,避免编码与字节码问题,并让工具链(如 LSP、调试器)正确找到解释器。
前置知识
阅读本节前,建议先了解:源码编译安装
基础概念
Python 解释器在启动时会读取若干环境变量。它们可大致分为三类:
| 类别 | 代表变量 | 作用 |
|---|---|---|
| 路径查找类 | PATH、PYTHONPATH | 决定命令与模块能否被找到 |
| 解释器行为类 | PYTHONUTF8、PYTHONHOME、PYTHONDONTWRITEBYTECODE | 改变解释器运行方式 |
| 工具链类 | VIRTUAL_ENV、PIP_INDEX_URL、PYTHONSTARTUP | 供虚拟环境与工具读取 |
变量名与平台约定:
- Windows 不区分大小写,习惯大写。
- macOS / Linux 区分大小写,始终使用大写。
- 值中若含空格或特殊字符,需要用引号包裹。
环境变量的作用范围
环境变量是「进程级」的:子进程会继承父进程的环境变量。因此在终端 export 后启动的 Python 能读到,而在修改前已启动的程序读不到。修改后需要重启终端或重新 source 配置文件。
语法与用法
Windows(PowerShell)
# 查看单个变量
echo $env:PYTHONUTF8
# 列出所有含 PYTHON 的变量
Get-ChildItem Env: | Where-Object { $_.Name -like "PYTHON*" }
# 临时设置(仅当前会话)
$env:PYTHONUTF8 = "1"
# 永久设置(当前用户)
[Environment]::SetEnvironmentVariable("PYTHONUTF8", "1", "User")
# 永久设置(所有用户,需管理员)
[Environment]::SetEnvironmentVariable("PYTHONUTF8", "1", "Machine")macOS / Linux(bash / zsh)
# 查看
echo $PYTHONUTF8
# 列出所有含 PYTHON 的变量
env | grep ^PYTHON
# 临时设置(仅当前会话)
export PYTHONUTF8=1
# 永久设置(bash)
echo 'export PYTHONUTF8=1' >> ~/.bashrc && source ~/.bashrc
# 永久设置(zsh,macOS 默认)
echo 'export PYTHONUTF8=1' >> ~/.zshrc && source ~/.zshrc
# 单次命令生效,不污染当前会话
PYTHONUTF8=1 python script.py详细说明
PATH:命令查找路径
PATH 是操作系统查找可执行文件的目录列表。只有 python 所在目录出现在 PATH 中,才能在任意位置直接输入 python。
# 查看 PATH
echo $PATH | tr ':' '\n' # macOS / Linux
echo $env:Path -split ';' # PowerShell
# 追加 Python 目录(macOS / Linux)
export PATH="/usr/local/bin:$PATH" # 放最前,优先级最高
# 检查某个命令解析到哪个文件
which python3 # macOS / Linux
where.exe python # WindowsPATH 的顺序至关重要:靠前的目录优先命中。若 /usr/bin 排在 /usr/local/bin 之前,python3 会命中系统版本。
PYTHONPATH:模块搜索路径
PYTHONPATH 用于向 sys.path 追加额外的模块搜索目录。
# 设置(多个路径用冒号分隔,Windows 用分号)
export PYTHONPATH="$HOME/pylibs:$HOME/shared"
# 验证是否生效
python3 -c "import sys; [print(p) for p in sys.path if 'pylibs' in p]"# Windows 使用分号分隔
$env:PYTHONPATH = "D:\pylibs;D:\shared"不要滥用 PYTHONPATH
PYTHONPATH 会全局影响所有 Python 进程,容易造成模块同名冲突。项目级依赖应通过包管理(pip install -e .)或 pyproject.toml 解决,而非堆叠 PYTHONPATH。
PYTHONHOME:解释器根目录
PYTHONHOME 用于指定标准库所在前缀,通常只在嵌入 Python 或自定义布局时使用。
# 指定自定义安装前缀
export PYTHONHOME=/opt/python-3.12.7
python3.12 -c "import sys; print(sys.prefix)"
# 查看当前 PYTHONHOME
python3 -c "import sys; print(sys.base_prefix)"不要随意设置 PYTHONHOME
一旦设置错误,解释器会找不到标准库并报 Fatal Python error: init_fs_encoding: failed to get the Python codec of the filesystem encoding。除非明确知道自己在做什么,否则不要设置此变量。
PYTHONUTF8:UTF-8 模式
Python 3.7+ 支持 UTF-8 模式,让文件系统编码、stdin/stdout 编码统一为 UTF-8。
# 开启 UTF-8 模式
export PYTHONUTF8=1
# 或使用 -X 参数(与 -X utf8 等价)
python3 -X utf8 script.py
# 验证
python3 -c "import sys; print(sys.flags.utf8_mode)"# Windows 上尤其重要,因为默认控制台编码为 GBK
[Environment]::SetEnvironmentVariable("PYTHONUTF8", "1", "User")PYTHONDONTWRITEBYTECODE 与 PYTHONPYCACHEPREFIX
# 不生成 __pycache__ 目录(.pyc 字节码缓存)
export PYTHONDONTWRITEBYTECODE=1
# 或把所有 .pyc 集中到一个目录(Python 3.8+)
export PYTHONPYCACHEPREFIX="$HOME/.cache/python-pyc"PYTHONSTARTUP:交互式启动脚本
PYTHONSTARTUP 指向一个 Python 脚本,每次启动交互式解释器时自动执行,常用于导入常用模块、定义辅助函数。
# 设置启动脚本
export PYTHONSTARTUP="$HOME/.pythonrc.py""""~/.pythonrc.py —— 交互式解释器启动时自动加载。"""
import sys
import os
from pathlib import Path
from datetime import datetime
def now() -> str:
"""返回当前时间的可读字符串。"""
return datetime.now().strftime("%Y-%m-%d %H:%M:%S")
print(f"Python {sys.version.split()[0]} 已就绪 | 当前时间:{now()}")VIRTUAL_ENV 与虚拟环境
创建虚拟环境(Virtual Environment)时,激活脚本会设置 VIRTUAL_ENV,工具链据此判断当前环境。
# 创建并激活
python3 -m venv .venv
source .venv/bin/activate # macOS / Linux
# .venv\Scripts\Activate.ps1 # Windows PowerShell
# 激活后该变量自动设置
echo $VIRTUAL_ENV
# 输出:/home/user/projects/demo/.venv
# 验证解释器已切换
python -c "import sys; print(sys.prefix)"
# 退出
deactivatepip 与包管理相关变量
# 镜像源
export PIP_INDEX_URL="https://pypi.tuna.tsinghua.edu.cn/simple"
export PIP_TRUSTED_HOST="pypi.tuna.tsinghua.edu.cn"
# 超时与重试
export PIP_DEFAULT_TIMEOUT=60
export PIP_RETRIES=5
# 缓存目录
export PIP_CACHE_DIR="$HOME/.cache/pip"
# 关闭版本检查提示
export PIP_DISABLE_PIP_VERSION_CHECK=1其他常用解释器变量
# 开启开发模式:显示警告、更详细的错误
export PYTHONDEVMODE=1
# 控制警告过滤器(等价于 -W 参数)
export PYTHONWARNINGS="default"
export PYTHONWARNINGS="ignore::DeprecationWarning"
# 优化模式(去掉 assert 与 __debug__ 代码)
export PYTHONOPTIMIZE=1 # 等价于 python -O
# 危险:跳过哈希随机化,仅测代码用
# export PYTHONHASHSEED=0
# 指定 site-packages 用户基础目录
export PYTHONUSERBASE="$HOME/.local"
# 关闭 .pth 文件处理与 site 模块(嵌入场景)
# export PYTHONNOUSERSITE=1各变量速查表:
| 变量 | 作用 | 推荐值 |
|---|---|---|
PYTHONUTF8 | UTF-8 模式 | 1 |
PYTHONDONTWRITEBYTECODE | 不生成 .pyc | 1 |
PYTHONSTARTUP | 交互式启动脚本 | ~/.pythonrc.py |
PYTHONPATH | 追加模块路径 | 尽量不设 |
PYTHONWARNINGS | 警告过滤 | 默认 |
PYTHONUNBUFFERED | 无缓冲输出 | 容器中 1 |
PYTHONUSERBASE | 用户级安装根 | 默认 |
PYTHONNOUSERSITE | 禁用用户站点目录 | 默认不设 |
调试环境变量是否生效
# 打印全部 Python 相关环境变量
env | grep -E "^(PYTHON|PIP|VIRTUAL_ENV|UV_)" | sort
# 在 Python 内查看
python3 -c "import os; [print(f'{k}={v}') for k, v in sorted(os.environ.items()) if k.startswith(('PYTHON','PIP'))]"
# 确认解释器实际读取到的搜索路径
python3 -c "import sys; print('\n'.join(sys.path))"
# 确认解释器是否处于 UTF-8 模式
python3 -c "import sys; print('utf8_mode =', sys.flags.utf8_mode)"
# 确认 site 模块配置
python3 -m site实战示例
案例一:Linux/macOS 完整配置文件
# 将以下内容追加到 ~/.bashrc 或 ~/.zshrc
# ===== Python 环境配置 =====
# 1. UTF-8 模式
export PYTHONUTF8=1
# 2. 不生成字节码缓存
export PYTHONDONTWRITEBYTECODE=1
# 3. 交互式启动脚本
export PYTHONSTARTUP="$HOME/.pythonrc.py"
# 4. 用户级可执行文件(pip install --user 安装的脚本)
export PATH="$HOME/.local/bin:$PATH"
# 5. 自定义模块路径(谨慎使用)
# export PYTHONPATH="$HOME/pylibs:$PYTHONPATH"
# 6. pip 镜像加速
export PIP_INDEX_URL="https://pypi.tuna.tsinghua.edu.cn/simple"
export PIP_DISABLE_PIP_VERSION_CHECK=1
# 7. uv 相关(若使用 uv)
export UV_PYTHON_PREFERENCE=managed
# ===== 配置结束 =====# 生效并验证
source ~/.bashrc
python3 -c "import sys, os; print('UTF-8 模式:', sys.flags.utf8_mode); print('PYTHONSTARTUP:', os.environ.get('PYTHONSTARTUP'))"案例二:Windows PowerShell 配置脚本
# 将以下内容保存为 ~/Documents/PowerShell/Microsoft.PowerShell_profile.ps1
# 或追加到 $PROFILE
# ===== Python 环境配置 =====
# UTF-8 模式(解决中文乱码)
$env:PYTHONUTF8 = "1"
# 不生成字节码缓存
$env:PYTHONDONTWRITEBYTECODE = "1"
# 交互式启动脚本
$env:PYTHONSTARTUP = "$HOME\.pythonrc.py"
# pip 镜像加速
$env:PIP_INDEX_URL = "https://pypi.tuna.tsinghua.edu.cn/simple"
$env:PIP_DISABLE_PIP_VERSION_CHECK = "1"
# 定义便捷函数:一键激活项目的虚拟环境
function Activate-Venv {
param([string]$Path = ".\.venv\Scripts\Activate.ps1")
if (Test-Path $Path) {
& $Path
Write-Host "已激活虚拟环境:$env:VIRTUAL_ENV" -ForegroundColor Green
} else {
Write-Host "未找到虚拟环境:$Path" -ForegroundColor Red
}
}
Set-Alias venv-activate Activate-Venv
# ===== 配置结束 =====# 查看 $PROFILE 路径并重新加载
$PROFILE
. $PROFILE
# 验证
python -c "import sys; print(sys.flags.utf8_mode)"案例三:Dockerfile 中配置环境变量
FROM python:3.12-slim
# Python 运行时环境变量(官方镜像推荐)
ENV PYTHONUNBUFFERED=1 \
PYTHONDONTWRITEBYTECODE=1 \
PYTHONUTF8=1 \
PIP_NO_CACHE_DIR=1 \
PIP_DISABLE_PIP_VERSION_CHECK=1
WORKDIR /app
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY . .
CMD ["python", "main.py"]为什么容器里要设 PYTHONUNBUFFERED=1
容器中若 stdout 被缓冲,日志不能实时输出,docker logs 会延迟甚至丢失尾部日志。设置该变量强制标准输出无缓冲,便于可观测性。
注意事项
- 修改后必须重开终端:已启动的终端不会感知图形界面中的环境变量修改。
- PATH 顺序:靠前优先,误把系统目录放在前会命中错误的 Python。
- PYTHONPATH 副作用:全局生效,易造成模块冲突,能不用则不用。
- PYTHONHOME 高风险:设置错误会导致解释器无法启动。
- Windows 别名干扰:
python.exe应用执行别名会抢占 PATH 中的真实 Python。 - 虚拟环境变量不可手工伪造:
VIRTUAL_ENV只是标记,真正决定解释器的是sys.prefix与可执行文件路径。 - 敏感信息不要放环境变量再提交:配置文件(如
.pydistutils.cfg)中避免写入密钥。
常见问题排查表:
| 现象 | 原因 | 解决 |
|---|---|---|
python: command not found | PATH 未含解释器目录 | 添加 PATH 并重开终端 |
| 中文乱码 / UnicodeDecodeError | 控制台编码非 UTF-8 | 设置 PYTHONUTF8=1 |
| 导入到错误的模块 | PYTHONPATH 干扰 | 移除 PYTHONPATH 或改用安装 |
| 解释器启动失败 | PYTHONHOME 错误 | 取消该变量 |
| pip 装到了系统目录 | 虚拟环境未激活 | 检查 sys.prefix |
| 反向代理下 pip 超时 | 网络问题 | 设置镜像与 PIP_DEFAULT_TIMEOUT |
最佳实践
- 只设置必要的变量:优先
PYTHONUTF8、PYTHONDONTWRITEBYTECODE、PYTHONSTARTUP。 - 避免全局 PYTHONPATH:用包安装与
pyproject.toml管理导入路径。 - 把配置写进版本化的 dotfiles:便于跨机器同步与审计。
- 虚拟环境内不覆盖全局变量:让 venv 自己管理
VIRTUAL_ENV。 - 容器中显式声明环境变量:使用
ENV指令,提升可复现性。 - 敏感配置使用密钥管理:不要写死在环境变量或仓库中,参见 敏感信息处理。
- 善用 dotenv:本地开发用
python-dotenv从.env加载,避免污染 Shell。
下一节
继续学习:多版本共存方案