第 2 章 · 02 .env 配置全解


文档摘要

第 2 章 · 02 .env 配置全解 本节摘要:本节逐项解读 AutoHedge 的环境变量配置。项目根目录的 是唯一权威样例,但只有 5 行——真正读懂它需要对照源码:谁在用、用什么名字、缺了会不会崩。本节先逐行拆 (JUPITERAPIKEY、OPENAIAPIKEY、ANTHROPICAPIKEY、WORKSPACEDIR、WALLETPRIVATEKEY),再回到源码里把「真正被读取的变量」补全(包括 漏写的 EXAAPIKEY,以及 用的 与样例的 不一致的坑),最后讲清 如何从当前目录向上递归找 。读完本节,你能配出一份真正能让项目跑通的 。 内容来源:原项目源码 、 、 、 ,精读并套用体系化模板。 ⚠️ 风险提示:涉及私钥。

第 2 章 · 02 .env 配置全解

本节摘要:本节逐项解读 AutoHedge 的环境变量配置。项目根目录的 .env.example 是唯一权威样例,但只有 5 行——真正读懂它需要对照源码:谁在用、用什么名字、缺了会不会崩。本节先逐行拆 .env.example(JUPITER_API_KEY、OPENAI_API_KEY、ANTHROPIC_API_KEY、WORKSPACE_DIR、WALLET_PRIVATE_KEY),再回到源码里把「真正被读取的变量」补全(包括 .env.example 漏写的 EXA_API_KEY,以及 ultra_tools.py 用的 SOLANA_PRIVATE_KEY 与样例的 WALLET_PRIVATE_KEY 不一致的坑),最后讲清 env_loader.py 如何从当前目录向上递归找 .env。读完本节,你能配出一份真正能让项目跑通的 .env

内容来源:原项目源码 .env.exampleautohedge/env_loader.pyautohedge/tools/exa_search_tool.pyautohedge/tools/ultra_tools.py,精读并套用体系化模板。

⚠️ 风险提示:涉及私钥。务必用测试钱包,切勿填主资产钱包私钥——任何泄露即资产清零。.env 已被 .gitignore 排除,确认别误提交。

学习目标

阅读完本节,你应当能够:

  1. 逐行读懂 .env.example,说出每项变量的用途与必填性。
  2. 对照源码,指出 .env.example 漏写不一致的变量(EXA_API_KEY、SOLANA_PRIVATE_KEY)。
  3. 说清 env_loader.py 的递归 .env 查找逻辑。
  4. 解释 override=False 为何不会覆盖已存在的环境变量。
  5. 配出一份真正能跑通.env

一、.env.example 全文逐行解读

项目根目录的 .env.example(共 12 行,5 个变量):

# Jupiter API (token price & search tools) # Get a key at https://portal.jup.ag JUPITER_API_KEY= # OpenAI (experimental agents) OPENAI_API_KEY= ANTHROPIC_API_KEY= WORKSPACE_DIR="agent_workspace" # Trading WALLET_PRIVATE_KEY=""

逐行解读:

变量 必填? 用途 谁在读
JUPITER_API_KEY 链上交易时必填 Jupiter Ultra API 的鉴权 key(token 报价、广播) ultra_tools.py_headers()
OPENAI_API_KEY 必须 调 GPT-4.1 / gpt-4o-mini(整个 Agent 系统的命脉) swarms 框架间接读取;cli.py 启动时校验
ANTHROPIC_API_KEY 可选(当前未用) 预留 Claude 模型接入,但 model_name 全是 OpenAI 当前代码无任何引用
WORKSPACE_DIR 可选 Agent 工作目录(swarms 用) swarms 框架内部
WALLET_PRIVATE_KEY 链上交易时必填 样例写的是这个名字,但真实代码读的是另一个——见第三节 (样例声明,代码不读这个名字)

💡 核心心法:.env.example 是「作者声明我以为我用了什么」,源码是「作者实际用了什么」。两者对不上是这个项目反复出现的毛病。永远以源码为准

二、源码真正读取的变量(补全清单)

把源码里所有 os.getenv(...) 找出来,才是真实的变量清单:

1. OPENAI_API_KEY——唯一启动门槛

cli.py 第 17-21 行,启动时主动校验:

load_env() if not require_openai_key(): Console().print( "[yellow]Warning: OPENAI_API_KEY not set. Set it in .env or export it.[/]" )

require_openai_key() 的实现(env_loader.py 第 30-32 行):

def require_openai_key() -> bool: """Return True if OPENAI_API_KEY is set (required for swarms gpt-4.x).""" return bool(os.getenv("OPENAI_API_KEY"))

注意:它只是警告,不阻断启动——但真到 Agent 调用时,swarms 会因为没 key 报 401。所以OPENAI_API_KEY 是跑通任何任务的硬门槛

2. EXA_API_KEY——样例漏写

情绪 Agent 的工具 exa_search(exa_search_tool.py 第 44-49 行):

api_key = os.getenv("EXA_API_KEY") if not api_key: raise ValueError( "EXA_API_KEY environment variable is not set" )

.env.example 完全没提 EXA_API_KEY。但只要 Director 把任务 handoff 给情绪 Agent,它就会调 exa_search,进而抛 ValueError。要跑通情绪分析,必须自己补一行:

EXA_API_KEY=你的_exa_key # 去 https://exa.ai 申请

3. JUPITER_API_KEY——链上鉴权

ultra_tools.py_headers() 读它(给 Jupiter Ultra API 请求加 x-api-key 头)。只做链上分析(get_order/get_holdings)或签名广播(execute_trade)时需要。

4. SOLANA_PRIVATE_KEY——样例名字不一致

这是本节最大的坑。样例写的是 WALLET_PRIVATE_KEY,但真正签名的 ultra_tools.py 读的是另一个名字。看 _get_keypair()(ultra_tools.py 第 57-66 行):

raw = os.getenv("SOLANA_PRIVATE_KEY") if not raw or not raw.strip(): raise ValueError("SOLANA_PRIVATE_KEY is required in .env to sign transactions")

即:你照 .env.exampleWALLET_PRIVATE_KEY=xxx,签名时代码却去找 SOLANA_PRIVATE_KEY,结果就是「明明填了却报缺 key」。正确做法是两个名字都填上(或只填代码真正读的那个):

# 代码真正读的名字(签名必需) SOLANA_PRIVATE_KEY=你的_base58_私钥 # 样例声明的名字(保留以防别的脚本读) WALLET_PRIVATE_KEY=你的_base58_私钥

⚠️ 现实澄清:变量名不一致是典型的「样例与代码脱节」。这种 bug 在生产里会让人调试到崩溃。学这套代码,养成「先 grep os.getenv 再说」的习惯。

三、env_loader.py:递归查找 .env 的逻辑

光配 .env 不够,还得让 Python 找得到它。env_loader.py 做的就是这件事——全文仅 33 行,设计却很巧:

import os from pathlib import Path from dotenv import load_dotenv def find_project_env() -> Path | None: """Find .env by walking up from cwd (so CLI/scripts work from any subdir).""" cwd = Path(os.getcwd()).resolve() for parent in [cwd, *cwd.parents]: env_file = parent / ".env" if env_file.is_file(): return env_file return None def load_env() -> None: """Load .env from project root; fall back to cwd. Does not override existing env.""" env_path = find_project_env() if env_path: load_dotenv(env_path, override=False) else: load_dotenv()

逐段拆解:

find_project_env:向上递归

  • Path(os.getcwd()).resolve() 拿到当前工作目录的绝对路径。
  • [cwd, *cwd.parents] 是一个列表:先看 cwd 自己,再看它的每一级父目录,直到磁盘根。
  • 对每一级,检查 .env 文件是否存在(is_file()),存在就返回它的路径。
  • 全找不到返回 None

意图:让你无论从项目的哪个子目录跑代码(比如 cd autohedge/tools && python xxx.py),都能自动找到项目根的 .env,而不是要求你必须 cd 到根目录。

load_env:加载且不覆盖

load_dotenv(env_path, override=False)

关键是 override=False:如果某个环境变量已经在系统环境里存在(比如你提前 set OPENAI_API_KEY=xxx),.env 里的值不会覆盖它。这在 CI/CD 或容器里很有用——可以用环境变量优先级覆盖文件配置。

💡 核心心法:override=False 体现的优先级是 系统环境变量 > .env 文件。调试时如果想强制用 .env 的值,要么改 True,要么先清掉系统变量。

四、.env 在 import 链里何时被加载

光有 load_env() 函数不够,得有人调它。AutoHedge 在两个入口都调了,形成双保险:

入口 1:autohedge/__init__.py 第 1-3 行——只要 import autohedge,load_env() 就执行:

from autohedge.env_loader import load_env load_env() from autohedge.main import AutoHedge

入口 2:autohedge/cli.py 第 17 行——REPL 启动时再调一次:

from autohedge.env_loader import load_env, require_openai_key load_env()

所以无论你用 example.py(里面 from autohedge import AutoHedge)还是 autohedge 命令,.env 都会被加载。重复调用 load_env() 无副作用(因为 override=False,且 load_dotenv 内部会去重)。

五、一份真正能跑通的 .env 模板

综合以上,推荐你把 .env 配成这样(把 .env.example 复制为 .env 后修改):

# === LLM(必填,否则任何任务都跑不动)=== OPENAI_API_KEY=sk-你的_openai_key # === 联网搜索(情绪 Agent 必需,样例漏写)=== EXA_API_KEY=你的_exa_key # === Jupiter(做链上分析/交易时填)=== JUPITER_API_KEY=你的_jupiter_key # === Solana 私钥(只在第 8 章签名时需要;务必用测试钱包)=== # 注意:代码真正读的是 SOLANA_PRIVATE_KEY,不是样例的 WALLET_PRIVATE_KEY SOLANA_PRIVATE_KEY=你的_base58_测试钱包私钥 WALLET_PRIVATE_KEY=你的_base58_测试钱包私钥 # === 可选 === WORKSPACE_DIR="agent_workspace" # ANTHROPIC_API_KEY 当前代码未用,可不填

⚠️ 风险提示:私钥那两行,只在学第 8 章链上签名时再填,且必须用测试钱包(新建一个,转少量测试 SOL 进去)。学第 3~7 章的多 Agent 编排,完全不需要私钥,这两行留空即可。

本节要点回顾

  1. .env.example 五项:JUPITER_API_KEY、OPENAI_API_KEY、ANTHROPIC_API_KEY(当前未用)、WORKSPACE_DIR、WALLET_PRIVATE_KEY。
  2. 必填只有 OPENAI_API_KEY:swarms 调 GPT 的硬门槛,缺了 Agent 一律 401;cli 启动会警告但不阻断。
  3. 样例漏写 EXA_API_KEY:情绪 Agent 的 exa_search 必需,必须自己补。
  4. 私钥变量名不一致:样例写 WALLET_PRIVATE_KEY,代码读 SOLANA_PRIVATE_KEY——两个都填最稳;务必用测试钱包。
  5. env_loader 递归查找:find_project_env 从 cwd 向上逐级找 .env,让你在任何子目录都能跑;load_dotenv(..., override=False) 保证系统环境变量优先于文件。
  6. 双保险加载:__init__.pycli.py 两处都调 load_env(),import autohedge 即触发。

下一节,我们用 example.py 跑通第一个分析任务,看 AutoHedge 初始化与 run() 的完整调用链。


发布者: 作者: 灏天文库 转发
评论区 (0)
U