【问题标题】:python os.environ, os.putenv, /usr/bin/envpython os.environ, os.putenv, /usr/bin/env
【发布时间】:2013-07-16 08:07:25
【问题描述】:

我想确保os.system('env') 不包含某些特定变量myname~/.bashrc 中导出为export myname=csj

因此,我写了下面的python代码:

import os

def print_all():
    print "os.environ['myname']=%s" % os.environ.get('myname')
    print "os.getenv('myname')=%s" % os.getenv('myname')
    os.system('env | grep myname')
    print

def delete_myname():
    if 'myname' in os.environ: os.environ.pop('myname')
    if os.getenv('myname'): os.unsetenv('myname')

print_all()

os.putenv('myname', 'csj2')
print "---------------------"
delete_myname()
print_all()

os.putenv('myname', 'csj3')
print "---------------------"
delete_myname()
print_all()

我想同时检查 os.environ['myname']os.getenv('myname') 然后删除它们(如果存在), 可以保证os.system('env | grep myname')一无所获。

但是,结果是:

os.environ['myname']=csj
os.getenv('myname')=csj
myname=csj

---------------------
os.environ['myname']=None
os.getenv('myname')=None

---------------------
os.environ['myname']=None
os.getenv('myname')=None
myname=csj3

我不明白为什么我在os.system('env | grep myname') 上仍然得到csj3

【问题讨论】:

  • 似乎发生了某种竞争情况。您是否始终如一地获得相同的结果?如果添加第 4 轮,myname=csj3 会持续存在,还是仅在第 4 轮中保持myname=csj4
  • 它总是得到相同的结果。实际上在我真正的python脚本中,第二个putenv()之间有很多东西/代码,让我很困惑..现在我在第二个putenv()之前放了一个time.sleep(1)和while [ 1 ]; do python env.py ; sleep 1; done来执行脚本,总是得到相同的结果。
  • 如果我删除一行if 'myname' in os.environ: os.environ.pop('myname'),令人惊讶的是,我在os.system('env | grep myname') 上一无所获,似乎解决了问题。虽然我还是不知道为什么……

标签: python


【解决方案1】:

一个好的做法可能是:

  • 删除myname环境变量(如果存在),
  • 运行你的函数
  • 在函数完成时恢复 myname 环境变量。

你可以使用 modified_environ 上下文管理器之类的东西轻松做到这一点,在这个 question 中描述。

with modified_environ('myname'):
    call_my_function()

【讨论】:

    【解决方案2】:

    来自docs

    注意:直接调用putenv()不会改变os.environ,所以最好修改os.environ。

    unsetenv 也有类似的警告:

    然而,对 unsetenv() 的调用不会更新 os.environ,因此实际上最好删除 os.environ 的项目。

    getenv 只是返回来自os.environ 的值,因为它是implementation shows,所以通过使用它,你会进入一个状态,当你从 python 中查找它时,它似乎没有设置该值,而它实际上是是在真实环境中。现在我能想到的唯一方法是使用 ctypes 调用 c getenv 函数...

    如果我修改您的代码以使用 os.environ 而不是调用 putenv/unsetenv 一切都按预期工作:

    import os
    
    def print_all():
        print "os.environ['myname']=%s" % (os.environ['myname'] if 'myname' in os.environ else "None")
        os.system('env | grep myname')
        print
    
    def delete_myname():
        if 'myname' in os.environ: os.environ.pop('myname')
    
    print_all()
    
    os.environ['myname'] = 'csj2'
    print "---------------------"
    print_all()
    delete_myname()
    print_all()
    
    os.environ['myname'] = 'csj3'
    print "---------------------"
    print_all()
    delete_myname()
    print_all()
    

    输出:

    $ myname=somevalue python2 test.py 
    os.environ['myname']=somevalue
    myname=somevalue
    
    ---------------------
    os.environ['myname']=csj2
    myname=csj2
    
    os.environ['myname']=None
    
    ---------------------
    os.environ['myname']=csj3
    myname=csj3
    
    os.environ['myname']=None
    

    【讨论】:

    • 是的,我认为如果只使用 os.environ 可以确保 /usr/bin/env 没有变量...但是导致其他团队的脚本使用 putenv() 做某事,我称他们为脚本。我没有很好的理由说服他们更改代码。我只是想尝试自己删除它。
    • 向他们展示 putenv/unsetenv 文档中的注释,getenv 只返回 os.environ 中的任何内容。这应该能说服他们。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-11-23
    • 2016-03-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-09-21
    相关资源
    最近更新 更多