vs code 不自动将 .env 文件注入终端环境变量,仅调试和语言服务器生效;终端需用 python-dotenv 显式加载,或通过 launch.json 的 envfile 配置调试环境。

VS Code 不会自动把项目根目录下的 .env 文件内容注入到所有运行方式的环境变量中——这是绝大多数人踩坑的起点。只有在特定上下文(比如调试、交互式窗口)下才会加载,终端里直接 python script.py 时完全不生效。
为什么 .env 在终端里运行脚本时没用?
VS Code 的集成终端本身就是一个独立 shell 进程,它只继承你系统或 shell 配置文件(如 ~/.zshrc)里定义的环境变量,不会主动读取当前工作区的 .env 文件。Python 插件的 python.envFile 设置也仅影响调试器和语言服务器(如 Pylance),对终端执行无任何作用。
- 现象:
os.environ.get("API_KEY")返回None,但你在.env里明明写了API_KEY=xxx - 验证方法:在 VS Code 终端里执行
echo $API_KEY,结果为空 - 根本原因:没有进程负责解析并导出
.env中的键值对到当前 shell 环境
launch.json 中的 env 和 envFile 怎么配才有效?
这两个字段只在 F5 调试或点击「调试 Python 文件」时起作用,是调试器启动子进程时显式传入的环境配置。
-
env:硬编码键值对,适合固定值,例如"PYTHONPATH": "${workspaceFolder}/src" -
envFile:指定一个文件路径(如"${workspaceFolder}/.env"),调试器会解析该文件并合并进环境;支持多行、注释、变量替换($HOME),但不支持嵌套引用($OTHER_VAR不会被展开) - 注意:
envFile的路径必须是绝对路径或基于${workspaceFolder}的相对路径,不能用~/或环境变量缩写
示例 launch.json 片段:
{
"version": "0.2.0",
"configurations": [
{
"name": "Python: Current File",
"type": "python",
"request": "launch",
"module": "pytest",
"envFile": "${workspaceFolder}/.env",
"env": {
"LOG_LEVEL": "DEBUG"
}
}
]
}
如何让终端运行也加载 .env?
唯一可靠、跨平台、不依赖插件的方式,是在 Python 脚本开头显式调用 python-dotenv 加载。
- 安装:
pip install python-dotenv(建议装在当前虚拟环境中) - 在入口脚本(如
main.py)最顶部添加:
from dotenv import load_dotenv
import os
<p>load_dotenv() # 自动查找并加载 .env 文件</p><h1>后续代码就能正常读取</h1><p>api_key = os.environ.get("API_KEY")</p>
- 如果
.env不在项目根目录,传入路径:load_dotenv(".config/dev.env") - 想强制重载或覆盖已有变量,加参数:
load_dotenv(override=True) - 这个方案与运行方式完全解耦:终端、交互式窗口、F5、打包后执行都生效
不同环境(dev/staging/prod)怎么动态切换?
别靠手动改 .env,用文件名区分 + load_dotenv() 的自动发现机制。
- 约定命名:
.env(通用)、.env.development、.env.production - 在代码中根据条件加载:
import os
from dotenv import load_dotenv
<p>env = os.getenv("ENVIRONMENT", "development")
load_dotenv(f".env.{env}") # 加载 .env.development 或 .env.production
load_dotenv(override=True) # 再加载 .env 做兜底覆盖</p>
- 启动时指定:
ENVIRONMENT=production python main.py - 或者通过
launch.json的env字段注入:"ENVIRONMENT": "staging"
真正容易被忽略的是:VS Code 的 Python 插件对 .env 的支持是“有选择性”的,它只服务于自己的内部流程(调试、补全、lint),并不接管你的终端行为。想让环境变量真正贯穿所有执行路径,就得在代码层做一次统一加载——这不是妥协,而是明确责任边界。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











