🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
Django

DjangoはPythonで書かれた、オープンソースウェブアプリケーションのフレームワークです。複雑なデータベースを扱うウェブサイトを開発する際に必要な労力を減らす為にデザインされました。

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

解決済

2回答

2314閲覧

[Django] django-environ を使用する際に、OSに設定されている環境変数名と全く同じ変数名の環境変数を.envに記載した場合にも、.envの値を読み取りたい

siruku6

総合スコア1382

Django

DjangoはPythonで書かれた、オープンソースウェブアプリケーションのフレームワークです。複雑なデータベースを扱うウェブサイトを開発する際に必要な労力を減らす為にデザインされました。

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0グッド

1クリップ

投稿2021/02/23 11:00

編集2021/07/24 02:19

そもそもできないんじゃないか、、、、とも思っていますが、誰かご存じかもしれないので念のため確認します。

やりたいこと

タイトルの通りです。

たとえば、OSにUSERという環境変数が設定されており、hogeだとします。
そして、.envファイルにもUSERという環境変数を設定し、そこにはuserという値を設定したとします。

このときに、userという値を読み取りたいです。
しかし、実際にはhogeという値しか読み取ることができませんでした。

ちなみにですが、OSに設定されていない環境変数であれば.envに設定した値を正しく読み取れることは確認できています。

あくまでも、OSと.envで重複する環境変数を設定している場合のみの問題になります。

試したこと

OSと.envどちらを優先させるかを指定するようなオプションがないか調べるため、公式ドキュメントでread_env()メソッドを調べてみましたが、それらしいオプションは見つかりませんでした。

https://django-environ.readthedocs.io/en/latest/index.html?highlight=read_env#environ.environ.Env.read_env

代替策を渋る理由

まぁ、

  • 環境変数名変えたら?
  • OSの環境変数消したら?

という話なのは薄々感じています。

感じてはいるんですが、複数のアプリケーション、複数種類のDBが動くOSにおいて、複数のアプリケーションの.env内で同じ環境変数名を使えたらいいな...というのが希望です。

(既に構築されていたアプリケーションがOSの環境変数を使っている模様...しかも、それがどのアプリケーションの環境変数なのかわからない.....

追記(2021/07/24)

こちらの記事に、python-dotenvであれば、OSの環境変数を上書きできるとの情報が載っていました。

https://maku77.github.io/python/env/dotenv.html

以下のようにして実施できるようです。

from dotenv import load_dotenv load_dotenv(override=True)

これと同じことを、django-environで行いたいだけなので、おそらく何かしら方法はあるはず(ちょっと時間がないのでここまでの記載にとどめておきますが、後で調べる予定です)

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ベストアンサー

回答としての結論

多分ですが、django-environを素直に利用する範囲においては、「USER.envで上書きする」ことは難しい気がします。

理由:read_envの仕組み

read_envの内部でやっていることは、大まかに書くと次のとおりです。

  • 指定された引数に基づいて、env_fileの読み込みを行い
  • os.environで未使用なキーに対して、初期値を与える
  • 更にoverridesの内容が存在した場合に、未使用なキーに対して初期値を与える

django-environのソースより
※内部的にはcls.ENVIRONに対する処理ですが、Envクラスではos.environが指定されているので同じとみなします

重要なのはos.environ[key] = valueではなくos.environ.setdefault(key, value)としているところです。
この実装のため、Djangoアプリケーション実行までに用意されている環境変数は原則として上書き利用することは出来ません。

無理やりする例

一見スマートに見えそうな解決方法を試しに考えてはみました。
...があまり意味がないか、django-environが本質的にやりたいことを捻じ曲げてそうな気はします

django-environのread_envを書き換えたクラスを用意する

python

1import os 2from environ import Env 3 4class MyEnv(Env): 5 ENVIRON = {} 6 7 @classmethod 8 def read_env(cls, env_file=None, **overrides): 9 super(MyEnv, cls).read_env() 10 for k, v in os.environ.items(): 11 cls.ENVIRON.setdefault(k, v)

上記のように、「ENVIRONの管理をos.environではなく自前dictにする」「read_envないで後追いでos.environを取り込む」とすることで、.envの方を優先的に利用することが出来ます。
この実装だと、環境変数にあったとしても.envが優先されるため、ファイルの中身を利用可能です。

※問題点として、read_envの呼び出しが必須になります
read_envsuper経由ではなく「setdefaultを使わない版に再実装」でも問題ないです

投稿2021/07/24 04:19

attakei

総合スコア2740

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

siruku6

2021/08/20 01:13

内部の実装にまで踏み込んだ回答をありがとうございます。 仮にできるとしても、非合理的な面のある方法になってしまうということ、把握しました。 素直に、djangoアプリケーションでもpython-dotenvも併用すればいいのではないかという気もしてきました。。 そもそも、OS上に大量に環境変数のある環境を使っているのが悪いのですが、、、、、 そこはどうしようもないというか、影響力を行使できないところなので、上手い方法を探っていきます。
guest

0

個人的な意見ですが、共通する変数、つまり定数のようなもののみPCの環境変数にするのが良いと思います。

実際、APIキーや、DBの情報もろもろは定数化されないはずです。

つまりkey:valueとすると、一種類のkeyに複数種類のvalueが存在することになります。

よって、プロジェクトごとの.envをおすすめします。
gitで管理しないように注意すればいいです。

投稿2021/02/23 14:43

prof

総合スコア179

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

siruku6

2021/02/25 05:28 編集

ありがとうございます。 私も、理想的にはそのようにするのが望ましいと感じております。 新しく構築するアプリケーションの環境変数は、.envに記載するつもりでおります。 ただ残念ながら、既に構築されているいずれかのアプリケーションがOS上に環境変数を設定しており、その変数を使用しているアプリケーションがどれなのかわかりません。 そして、その、OSに設定されているのと同じ名前の環境変数を.envに記載して使いたいのです。 django-environにおいて、それを実現する方法はないのでしょうか、というのがこの質問の趣旨になります。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.36%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問