os.environ['foo']和os.getenv('foo')何时不匹配?

43

我有一个小的Python 应用程序,通过subprocess.Popen启动,它以环境变量的形式传递一些参数。我通过将环境结构传递到Popen调用中来实现这一点。然后通过os.getenv读取变量。

或者更确切地说,它曾经是那样读取的。在Windows上,它工作得很好。但在我们的FreeBSD服务器上,os.getenv返回我们传递的所有参数的None。奇怪的是,os.environ的值完全正确,并且仅仅将所有os.getenv('foo') 的调用改为 os.environ [ 'foo']就可以在两个平台上正常工作。

为什么这些值不同?什么时候使用其中之一比另一个更合适?

1个回答

36

os.environ是在导入os模块时创建的,除非直接修改,否则它不会反映之后发生的环境更改。有趣的是,os.getenv()在CPython中并没有实际获取最新的环境变量,至少在CPython中不是这样。你看,在CPython中,os.getenv()似乎只是os.environ.get()的包装器(参见http://hg.python.org/cpython/file/6671c5039e15/Lib/os.py#l646)。因此,使用os.getenv()的主要原因与上述实现是当你想要在os.environ的键中未找到环境变量名称时返回一个默认值,而不是抛出KeyError或其他异常,同时想要节省一些字符。

FreeBSD上的实现可能存在一些奇怪的技巧,导致其表现不同,但我不确定为什么会这样。如果可能的话,请查看你使用的FreeBSD机器上的os.py副本。


在Windows 10上,os.putenv('abc', '123')无法工作,也就是说,新变量没有被设置。然而,os.environ['abc'] = '123'可以工作,并且随后os.getenv('abc')也可以工作。 - coder.in.me
4
经过进一步的检查,原因在于putenv()实际上并没有将环境变量存储在os.environ中;相反,environ.__setitem__()调用了putenv()并且还在本地存储数据,而getenv()environ.__getitem__()都没有实际查询环境本身,它们都是基于os.environ所存储的数据进行操作。这种实现方式相当令人困惑。 - JAB

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接