使用copy.deepcopy在python中的os.environ上似乎是破碎的



我可能只是错过了有关OS.Environ或copy.deepcopy工作方式的一些文档,但是看来Copy.deepcopy在OS.Environ上不起作用。但是,如果我将OS.Environ重建为新词典,则可以正常工作。这是我的示例代码:

import copy
import os
tcsh_loc = '/bin/tcsh'
safe_dict = {}
for key in os.environ.keys():
    safe_dict[key] = os.environ[key]
safe_dict['SAFE_ENV'] = 'non-leaked-var'
os.spawnv(os.P_WAIT, tcsh_loc, [tcsh_loc, '-c', 'echo $SAFE_ENV'])
os.spawnve(os.P_WAIT, tcsh_loc, [tcsh_loc, '-c', 'echo $SAFE_ENV'], safe_dict)
unsafe_dict = copy.deepcopy(os.environ)
unsafe_dict['UNSAFE_ENV'] = 'leaked-var'
os.spawnv(os.P_WAIT, tcsh_loc, [tcsh_loc, '-c', 'echo $UNSAFE_ENV'])
os.spawnve(os.P_WAIT, tcsh_loc, [tcsh_loc, '-c', 'echo $UNSAFE_ENV'], unsafe_dict)

我期望的是:

SAFE_ENV: Undefined variable.
non-leaked-var
UNSAFE_ENV: Undefined variable.
leaked-var

但是我离开的是:

SAFE_ENV: Undefined variable.
non-leaked-var
leaked-var
leaked-var

这意味着某种程度上的unsafe_dict['UNSAFE_ENV'] = 'leaked-var'分配以某种方式"泄漏"到OS.Environ中,大概是从OS.Environ不像我预期的那样深入的。

我认为这是某种已知的行为,但至少在使用os.spawnev()之类的东西方面,这对我来说确实是不希望的。我有一个笨拙的解决方法,但是我有兴趣了解发生了什么,如果有一个比循环更优雅的解决方案...

os.environ是类型os._Environ,而不是列表或字典。逻辑的是,os._Environ实例的副本也将修改环境。

请参阅os._Environ.__setitem__()功能。它将值存储在 2个ploce 中,一旦使用putenv()并将其分配给self._data字典中的键。

def __setitem__(self, key, value):
    key = self.encodekey(key)
    value = self.encodevalue(value)
    self.putenv(key, value)
    self._data[key] = value

您可以更轻松地重建它:只需使用dict(os.environ)

简单测试:

import os
a=os.environ
b=dict(os.environ)
print type(a), type(b)
# -> <type 'instance'> <type 'dict'>
print a['PWD'], b['PWD']
# -> /home/max /home/max
b['PWD']='/fooo'
print a['PWD'], b['PWD']
# -> /home/max /fooo

相关内容

最新更新