pythonでシステム環境変数を読み込む-その1


概要・目的

os.environを使ってシステム環境変数を取得する。
アプリケーション内で使用する設定情報は設定ファイル等に書いてDIできるようになっているが、
設定ファイルの数が多い、または開発状況(develop-staging-release)が複雑な場合は
メンテナンスコストが増大し、ミスする可能性がアップする。
システム環境変数に設定情報を保持することで、設定ファイルのメンテナンスコストを下げることはできないかと考え、
システム環境変数を利用するプログラムを調べてみた。

os.environについて深掘り

os.environはシステム環境変数を辞書型で保持している。
pythonが実行されるまでのシステム環境変数を参照できる。
osライブラリ

システム環境変数を取得するには

システム環境変数を取得するには、os.environにシステム環境変数名を指定する。
コマンドプロンプト上で実行したSET %システム環境変数名%と同じ結果となる。

$ python
Python 3.8.1 (tags/v3.8.1:1b293b6, Dec 18 2019, 23:11:46) [MSC v.1916 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import os
>>> print(os.environ['HOMEDRIVE'])
C:
>>>

存在しないシステム環境変数名を指定するとKeyErrorが発生する。

$ python
Python 3.8.1 (tags/v3.8.1:1b293b6, Dec 18 2019, 23:11:46) [MSC v.1916 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import os
>>> os.environ['TEST']
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "C:\Program Files\Python38\lib\os.py", line 673, in __getitem__
    raise KeyError(key) from None
KeyError: 'TEST'
>>>

存在しないシステム環境変数名に例外が発生させたくない場合は、os.getenv(key, default=value)を使用する。
keyが存在しない場合は、defaultの指定値が返される。defaultを指定しない場合はNoneとなる。
os.environ.get(key)も同様となる。os.getenv(key, default=value)os.environ.get(key)のエイリアスである。

$ python
Python 3.8.1 (tags/v3.8.1:1b293b6, Dec 18 2019, 23:11:46) [MSC v.1916 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import os
>>> value = os.getenv("TEST", "defaultvalue")
>>> print(f"TEST={value}")
TEST=defaultvalue
>>>

システム環境変数を更新するには

os.environが辞書型なのでシステム環境変数と値をセットするだけ
システム環境変数名が存在しない場合は追加され、存在する場合は上書きされる。
削除する場合はdel文を使って削除する。del os.environ[システム環境変数名]

$ python
Python 3.8.1 (tags/v3.8.1:1b293b6, Dec 18 2019, 23:11:46) [MSC v.1916 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import os
>>> value = os.environ["TEST"]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "C:\Program Files\Python38\lib\os.py", line 673, in __getitem__
    raise KeyError(key) from None
KeyError: 'TEST'
>>> os.environ["TEST"] = "PYTHON"
>>> value = os.environ["TEST"]
>>> print(f"TEST={value}")
TEST=PYTHON
>>> os.environ["TEST"] = "PYTHON3"
>>> value = os.environ["TEST"]
>>> print(f"TEST={value}")
TEST=PYTHON3
>>> del os.environ["TEST"]
>>> value = os.environ["TEST"]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "C:\Program Files\Python38\lib\os.py", line 673, in __getitem__
    raise KeyError(key) from None
KeyError: 'TEST'
>>>

os.environを直接変更せずにシステム環境変数をセットする関数もある。
getenvと対になるputenv(key, value)でシステム環境変数に追加や更新ができるが、公式ドキュメントにはこのような注意書きがある。

os.putenv引用

putenv() がサポートされている場合、 os.environ のアイテムに対する代入を行うと、自動的に putenv() の対応する呼び出しに変換されます。直接 putenv() を呼び出した場合 os.environ は更新されないため、実際には os.environ のアイテムに代入する方が望ましい操作です。
引数 key, value を指定して 監査イベント os.putenv を送出します。

putenv()で更新したシステム環境変数がos.environに反映されないなんてバグとしか思えないのだが、辞書型のデータをして扱えばよい。