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

Я хочу, чтобы 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

Я не понимаю, почему у меня все еще есть csj3 на os.system('env | grep myname')?

Ответ 1

Из docs:

Примечание: Вызов putenv() напрямую не меняет os.environ, поэтому лучше изменить os.environ.

Для unsetenv существует аналогичная операция:

однако вызовы unsetenv() не обновляют os.environ, поэтому на самом деле предпочтительнее удалять элементы os.environ.

getenv просто возвращает значение из os.environ, так как это реализация показывает, поэтому, используя это, вы попадаете в состояние, где кажется, что значение не задано, когда вы просматриваете его с помощью python, в то время как оно находится в реальной среде. Единственный способ получить это сейчас, я могу думать, что это будет вызов функции c getenv с использованием ctypes...

Если я изменю свой код, чтобы использовать os.environ isnstead of call 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

Ответ 2

Хорошей практикой может быть:

  • удалить переменную среды myname (если она существует),
  • выполните вашу функцию.
  • восстановить переменную среды myname при завершении функции.

Ю может легко справиться с чем-то вроде диспетчера контекста modified_environ в этом вопросе .

with modified_environ('myname'):
    call_my_function()