direnv 加载 python 环境变量不生效,主因是 shell hook 未激活;需在 ~/.zshrc 或 ~/.bashrc 中添加 eval "$(direnv hook $shell)" 并 source;.envrc 中禁止裸 export,须先 direnv allow 或用 export_with_env;layout python 可自动管理虚拟环境与 pythonpath,避免手动 source venv/bin/activate;git clone 后必须手动 direnv allow 才能加载 .envrc。

direnv 加载 Python 项目环境变量不生效?先确认 shell hook 是否已激活
绝大多数情况下,direnv 看似“没反应”,其实是 shell 没加载它的 hook。它不会自动注入,必须手动在 shell 配置里显式调用 direnv hook $SHELL 并 eval。
- zsh 用户检查
~/.zshrc是否有类似eval "$(direnv hook zsh)",且该行未被注释、未放在条件判断后导致跳过 - bash 用户同理检查
~/.bashrc,注意不要写成direnv hook bash(漏掉eval) - 改完配置后必须执行
source ~/.zshrc或新开终端,direnv status应显示 “hook installed” - 如果用 Oh My Zsh,某些插件(如
direnv插件)会自动处理,但优先级可能低于你手写的 hook —— 冲突时以direnv status输出为准
Python 项目中 .envrc 文件该写什么?别直接 export PYTHONPATH
.envrc 不是 .bashrc 的子集,它默认拒绝未授信的导出操作。直接写 export PYTHONPATH=... 会被 direnv 拦住,报错 direnv: error unallowed export: PYTHONPATH。
- 必须先运行
direnv allow授信当前目录的.envrc,否则任何export都被静默忽略 - 推荐用
layout python(需安装direnv的 python layout 插件),它会自动设置PYTHONPATH、PATH和虚拟环境激活逻辑 - 若需手动控制,用
export_with_env替代裸export:例如export_with_env PYTHONPATH "$PWD/src",它会自动加入白名单 - 避免硬编码绝对路径,多用
$PWD或$(pwd),否则换机器或 clone 路径变就失效
virtualenv / venv 激活和 PYTHONPATH 冲突?layout python 不等于 source bin/activate
layout python 本质是让 direnv 管理 Python 环境上下文,不是简单调用 source venv/bin/activate。两者混用会导致 PYTHONPATH 被覆盖、解释器路径错乱。
- 如果项目已有
venv目录,layout python会自动识别并激活;不需要再写source venv/bin/activate - 若同时设置了
PYTHONPATH(比如指向本地模块),确保它在layout python之后设置,否则 virtualenv 的site-packages可能被屏蔽 - 验证是否生效:运行
which python应指向项目venv/bin/python,python -c "import sys; print(sys.path)"应包含你的源码路径 - 注意
layout python默认不修改PYTHONPATH—— 它靠sys.path[0]和site-packages机制工作,额外路径仍需显式加
Git clone 后 direnv 拒绝加载?.envrc 权限和信任链要重设
每次 git clone 新项目,即使内容完全一样,direnv 也会视为新目录,.envrc 默认被禁用。这不是 bug,是安全模型强制要求人工确认。
立即学习“Python免费学习笔记(深入)”;
- 进入目录后必须手动运行
direnv allow,它会在~/.direnv/allow下生成哈希签名文件 - 不要复制别人的
~/.direnv/allow文件 —— 哈希基于路径+内容+mtime,跨机器无效,还可能触发校验失败 - 如果项目带
.envrc但团队希望开箱即用,可改用.envrc.toml(需启用 experimental TOML 支持),但依然绕不开首次allow - CI 或自动化脚本里不能依赖
direnv自动生效,应改用venv+ 显式PYTHONPATH设置
最常被忽略的是:direnv allow 只对当前目录生效,子目录不会继承;如果项目有嵌套子模块且各自有 .envrc,每个都得单独 allow。










