为何source无export的.env文件后,echo可取变量但Python的os.environ.get不行?
环境变量未被Python读取的深层原因解析
1. source命令的核心逻辑
source(或等价的.)是Shell内置命令,它的唯一作用是在当前Shell进程中直接执行目标脚本的所有命令,不会创建新的子Shell进程。这意味着脚本里的变量赋值、配置变更都会直接作用于当前Shell会话:
- 当脚本里写
NAME=Bob时,Shell会将NAME设为本地变量:仅在当前Shell进程内可见,不会自动传递给任何子进程。 - 当脚本里写
export NAME=Bob时,Shell会将NAME标记为环境变量:当前Shell的所有子进程都会继承这个变量。
2. 子Shell与环境变量的继承规则
Shell中执行外部命令(比如python3 x.py)时,会自动创建一个子进程来运行该命令。子进程的环境变量完全来自父Shell的环境变量集合,但无法访问父Shell的本地变量。
针对你的操作场景:
- 执行
(source .env.test; echo $NAME):括号()会创建一个子Shell,source在这个子Shell里执行脚本,设置了本地变量NAME,而echo也在同一个子Shell进程中运行,因此能读取到本地变量,输出Bob。 - 执行
(source .env.test; python3 x.py):同样在子Shell中source脚本得到本地变量NAME,但python3是这个子Shell的子进程,子进程只能继承父进程的环境变量,读不到本地变量,因此Python输出None。
添加export后,NAME成为环境变量,无论是同Shell的echo还是子进程的Python,都能读取到这个变量,所以两种执行方式都输出Bob。
3. Python读取环境变量的本质
Python的os.environ.get()读取的是当前Python进程自身的环境变量表,这个表是Python进程启动时,从父Shell(启动它的Shell进程)继承来的环境变量集合。只有父Shell中被标记为环境变量的内容,才会出现在这个表里。
核心结论
- 未加
export的变量是Shell本地变量,仅当前Shell可见,不会传递给子进程; - 加
export的变量是环境变量,会被所有子进程继承; - Python只能读取自身进程的环境变量,这些变量来自父Shell的环境变量集合。
内容的提问来源于stack exchange,提问作者101010
相关产品推荐
相关产品推荐

