python os.environ, os.putenv, /usr/bin/env

2020-04-02 06:09发布

I want to ensure os.system('env') not contain some specific variable myname which is export in ~/.bashrc as export myname=csj

Therefore, I wrote below python code:

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()

I think examine both os.environ['myname'] and os.getenv('myname') and then delete them if exist, can ensure os.system('env | grep myname') get nothing.

However, the result is:

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

I don't understand why I still got csj3 on os.system('env | grep myname')?

标签: python
2条回答
The star\"
2楼-- · 2020-04-02 06:34

From the docs:

Note: Calling putenv() directly does not change os.environ, so it’s better to modify os.environ.

For unsetenv there is a similar warining:

however, calls to unsetenv() don’t update os.environ, so it is actually preferable to delete items of os.environ.

getenv just returns the value from os.environ, as it's implementation shows, so by using it you get into a state where it seems the value isn't set when you look it up from python, while it acutally is in the real environment. The only way to get it now I can think of would be to call the c getenv function using ctypes...

If i modify your code to use os.environ isnstead of calling putenv/unsetenv everything works as expected:

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()

output:

$ 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
查看更多
家丑人穷心不美
3楼-- · 2020-04-02 06:47

A good practice could be:

  • delete the myname environment variable (if it exists),
  • run your function
  • restore the myname environment variable at function completion.

Yu can do that easily with something like the modified_environ context manager describe in this question.

with modified_environ('myname'):
    call_my_function()
查看更多
登录 后发表回答