Pythonで環境変数(os.environ)を使う: 取得、追加、更新、削除
目次
Pythonで環境変数を使う
Pythonでは標準ライブラリのos.enrvionを使うと、環境変数にアクセスすることができます。
特定の環境変数の値を取得したり、設定したりすることが可能です。
結論から言うと、環境変数は↓のように設定/取得します。
import os os.environ['MYVAR'] = 'hello' myvar = os.environ['MYVAR'] print(myvar) # hello
この記事ではos.environ
を使った環境変数の設定について具体的に↓を見ていきます。
環境変数とは?
os.envrionとは?
環境変数の取得
環境変数の設定
環境変数の更新
環境変数の削除
環境変数とは?
環境変数とはプロセスに設定できる変数のことを言います。
プロセスとは、アプリケーションを起動したときに作成されるアプリケーションの単位となるものです。
アプリケーションを起動することとプロセスを起動することはほぼ同じ意味です。
プロセス内でメインスレッドが起動し、開発者がスクリプトなどに書いたコードが実行されます。
環境変数はプロセス内から設定/参照することができます。
また、子プロセスに親プロセスの環境変数を引き継がせることも出来ます。
基本的にはプロセス内の環境変数の変更は、そのプロセス内に限定されます。
Pythonのスクリプトを走らせるとプロセスが起動しますが、そのプロセスからシステム全体の環境変数を変えることはできません。
例外としてそのスクリプトから新しく起動する子プロセスにおいては、親プロセスであらかじめ環境変数を設定しておくことで切り替えができます。
os.envrionとは?
os.environ
とは環境変数が保存されている辞書のことです。
os.environ
はos
モジュールをインポートすると使うことができます。
import os
os.environ
はos._Environ
型の辞書です。
print(type(os.environ)) # <class 'os._Environ'> print(isinstance(os._Environ, dict)) # False
辞書とは言いますが、辞書のようなインターフェースを持っているだけであって↑のようにdict
を継承しているわけではありません。
os.environ
には環境変数が保存されており、ここに保存されている環境変数を変更したり新しく加えたりすることで現在のプロセスの環境変数を変更することができます。
この辞書に保存できるのは文字列のみになっています。
環境変数の取得
os.environ
から環境変数を取得するには↓のように角カッコにキーを渡してアクセスします。
myvar = os.environ['MYVAR'] print(myvar) # hello
↑の場合、↓のようにスクリプトを起動している場合はmyvar
には「hello
」と言う文字列が代入されます。
$ MYVAR=hello python script.py hello
キーが存在しない場合は例外KeyError
が送出されます。
try: os.environ['NOTHING'] except KeyError as e: print(e) # 'NOTHING'
↓のようにget()
メソッドを使うことも出来ます。
myvar = os.environ.get('MYVAR') print(myvar) # hello
get()
を使う場合は第2引数にデフォルト値を指定することができます。
myvar = os.environ.get('NOTHING', 'world') print(myvar) # world
↑の場合、NOTHING
は存在しない環境変数ですが、その値の代わりにworld
がget()
から返されます。
環境変数の設定
os.environ
に環境変数を設定するには↓のようにキーに対して代入を行います。
os.environ['MYVAR'] = 'hello' print(os.environ['MYVAR']) # hello
os._Environ
のメソッド__setitem__
が呼ばれ、内部的にはputenv()
が呼ばれます。
すでにキーの値がセットされている場合は加算代入も行えます。
os.environ['MYVAR'] += ' world' print(os.environ['MYVAR']) # hello world
文字列以外の値を代入しようとすると例外TypeError
が送出されます。
try: os.environ['MYVAR'] = 1 except TypeError as e: print(e) # str expected, not int
環境変数の更新
os.environ
に設定されている環境変数を更新するには設定の時と同じように角カッコでキーを指定して代入します。
os.environ['MYVAR'] = 'hello' print(os.environ['MYVAR']) # hello
update()
メソッドを使っても更新することができます。この場合は引数のキーがそのままキーに、値が値になります。
os.environ.update(MYVAR='world') print(os.environ['MYVAR']) # world
update()
を使う場合は一度に複数の環境変数を更新できます。
os.environ.update(AAA='This is AAA', BBB='This is BBB') print(os.environ['AAA']) # This is AAA print(os.environ['BBB']) # This is BBB
環境変数の削除
os.environ
から環境変数を削除するにはdel
キーワードを使います。
os.environ['MYVAR'] = 'hello' print(os.environ['MYVAR']) # hello del os.environ['MYVAR'] print(os.environ.get('MYVAR', 'nothing')) # nothing
↑の場合、MYVAR
という環境変数を設定していますが、そのあとにdel
でMYVAR
を削除しています。
そのためget()
でMYVAR
を参照できず、デフォルト値のnothing
が返されます。
os._Environ
のメソッド__delitem__()
が呼ばれ、内部的にはunsetenv()
が呼ばれます。
存在しない環境変数にdel
を使った場合はKeyError
になります。
try: del os.environ['NOTHING'] except KeyError as e: print(e) # 'NOTHING'
↑の場合はNOTHING
の参照時点でKeyError
が発生しています。そのためdel
自体は実行されていません。
またpop()
メソッドを使っても環境変数を削除することができます。
os.environ['MYVAR'] = 'hello' myvar = os.environ.pop('MYVAR') print(myvar) # hello print('MYVAR' in os.environ.keys()) # False
↑の場合MYVAR
という環境変数を設定しています。
それをpop()
で取得して同時に削除します。
'MYVAR' in os.environ.keys()
でos.environ
の中にキーが含まれているか確認すると、結果はFalse
になります。
つまりMYVAR
という環境変数が削除されたことがわかります。
ほかにはclear()
を使っても環境変数を削除できます。
clear()
は辞書の中身を空にします。
print(len(os.environ.keys())) # 35 os.environ.clear() print(len(os.environ.keys())) # 0
↑の場合os.environ
のキーの数は最初は35
ありましたが、clear()
後は0
になっているのがわかります。
マルチスレッドで環境変数を使う
環境変数はプロセスに設定されます。
そのためマルチスレッドなプログラムにおいても環境変数を参照することができます。
import os import threading import time def func1(): time.sleep(5) os.environ['STATUS'] = 'stop' print('func1 done') def func2(): while True: time.sleep(1) print('func2 running') if os.environ.get('STATUS', 'running') == 'stop': break print('func2 done') t1 = threading.Thread(target=func1) t2 = threading.Thread(target=func2) t1.start() t2.start() t1.join() t2.join()
↑のコードを実行すると↓のような結果になります。
func2 running func2 running func2 running func2 running func1 done func2 running func2 done
↑の場合、func1()
とfunc2()
がスレッドの関数として起動します。
そしてfunc1()
は5
秒後に環境変数STATUS
の値を設定します。
func2()
ではその環境変数STATUS
の値を監視して、値がstop
になったら無限ループから脱出しています。
ただこのようなコードは一応書けますが、あまり一般的ではないかもしれません。
普通はただの変数とミューテックスなどの排他的制御処理を行います。
またthreading
モジュールにはLock
があるのでこれを使うのがより一般的と言えます。
またスレッドセーフ的にどうかというところですが、ソースコードを見たところos._Environ
の各種メソッドはデータにアクセスする際に排他的制御を行っていないようです。
そのため↑のコードは意図しない動作になる可能性もあります。
ただPythonにはGIL(グローバルインタプリタロック)が備わっているため、大きく問題化することはもしかしたらないのかもしれません。
ですが、マルチスレッドプログラミングにおいては排他的制御はした方が良いのが通常かと思われます。
そのため実装する場合は排他的制御を検討してみてください。
おわりに
今回はPythonの環境変数について見てみました。
環境変数は慣れると非常に便利な仕組みです。サーバーの管理が楽になったりするのでぜひブックマークお願いします。
(^ _ ^) | 環境変数のせい |
(・ v ・) | 環境変数が良かった |