質問をすることでしか得られない、回答やアドバイスがある。

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

ただいまの
回答率

90.49%

  • Python 3.x

    10228questions

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

  • Flask

    362questions

    FlaskはPython用のマイクロフレームワークであり、Werkzeug・Jinja 2・good intentionsをベースにしています。

開発環境ごとにconfigを読み替える

解決済

回答 3

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 684

test.py/staging.py/production.pyのそれぞれ3つのconfigファイルがあります。
この三つの環境の違いは、year.pyはローカル環境、staging.pyはGAE環境、production.pyはGKE環境です。
下記のコードにどう追記していけば、これらのconfigの読み替えができるようしたいです。
現状、test.pyのconfigを読むように書いていますが、これを3つ増やすだけでは駄目だと思っています。
条件分岐か何かかくべきでしょうか? こうかけるというのがあれば、ご教示いただけませんでしょうか?

wsgi.py

* create_appは、initファイルからimport
import os
from xxx import create_app

if os.environ.get("DEBUG"):
    logging.basicConfig(level=logging.DEBUG)

if __name__ == '__main__':
    app = create_app('test')
    app.run(host='127.0.0.1', port=8080, debug=True)

追記

test.py(ローカルで動かす用のconfigファイル)

import os
from pathlib import Path
from module.config.base import Config

basedir = Path(__file__).parent.parent.parent


class LocalConfig(Config):
    TESTING = True
    DEBUG = True
    SQLALCHEMY_DATABASE_URI = "sqlite:////" + os.path.join(basedir, "test.db")

    @staticmethod
    def init_app(app):
        pass
  • 気になる質問をクリップする

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • mather

    2018/10/09 18:12 編集

    config.py ファイルを参照するようにしておいて、 configファイルそのものを置き換えることは出来ないのですか?

    キャンセル

  • sequelanonymous

    2018/10/09 19:32

    すみません、イメージわかないのでもう少し具体的に教えて頂けませんでしょうか?

    キャンセル

回答 3

checkベストアンサー

+2

以下のようにして環境に配置したときに staging.py を config.py にコピーすればいいのでは?

import os
from config import create_app, app_name

debug = False

if os.environ.get("DEBUG"):
    logging.basicConfig(level=logging.DEBUG)
    debug = True

if __name__ == '__main__':
    app = create_app(app_name())
    app.run(host='127.0.0.1', port=8080, debug=debug)

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/10/09 19:38

    app_nameを勝手に追加しましたが、引数が環境別で違うだけなら create_app() で十分なのでは。

    キャンセル

  • 2018/10/09 19:45

    ありがとうございます。多分、誤解が生じている気がしているかもしれません。上記、私が記載したコードは、wsgi.pyに書いており、各環境ごとのconfigファイルは別にあり、creat_app()の引数にそのconfigファイル名を記載することで読み込むというようにしています。環境ごとにconfigファイルを読み込むようにしたいです。現状だと、test.pyというconfigファイルを読み込むには、creat_app('test')と指定する必要があります。if __name__ == '__main__':がtrueのときという条件つきで。これをcreat_app('staging')やcreat_app('production')というようにできればよいのかなと勝手なイメージを考えています。

    キャンセル

  • 2018/10/09 19:47

    from test import create_app
    ここで test.py を読み込んでいるんじゃないんですか?

    キャンセル

  • 2018/10/09 19:52

    実行後にimportするファイルを変更することはできません。できることと言えば別のPythonプロセスを呼び出して実行するか、execを使ってファイルの内容を評価するかですが、 execは危険なためあくまでも最終手段だと思ってくださいね。

    設定ファイルという話で言うならPythonファイルである必要はないはずで、例えば configparser を使うべきかと思います。

    キャンセル

  • 2018/10/09 20:36

    すみません、私の記載ミスでした。from test import create_appのtestは、creat_app('test')で指定しているtestとは異なります。モジュール名が入ります。転記する際に修正したところ、たまたま名前がかぶりました。

    キャンセル

  • 2018/10/09 23:24

    なんにせよ、すでに回答したとおり読み込むPythonファイルを切り替える手法は使うべきではないと思います。
    configparserやその他設定ファイルで挙動を切り替えることを考えてみてください。

    キャンセル

  • 2018/10/09 23:57

    ありがとうございます。言葉足らずで伝わらづらかったと思いますが、当質問の本質的な部分は、実行される環境ごとに読み込むconfigファイルを切り替えられるか?できるならばどうできるか?です。
    やりたいことは、実行される環境ごとに読み込むconfigを変えたいです。つまり、おそらく__name__の値ごとに異なるかなと思っています。
    test.pyはローカル環境、staging.pyは、docker上かつGAE、production.pyはdocker 上かつGKEです。

    キャンセル

  • 2018/10/10 02:53

    あなたが本質的と思っている以上は何も言いませんが、私からは憶測と思い込みが先行してしまって本当は何がしたいのか冷静に整理できていないように見えます。

    __name__の値はモジュールとして読み込まれたときの完全修飾名です。
    https://docs.python.jp/3/reference/import.html?highlight=name#__name__
    実行してみるとわかりますが、importしたファイルごとで__name__で参照される値は決まりますし、環境による違いはないはずです。
    あなた自身が環境別の値を環境変数などで設定しない限り、環境の違いをアプリケーションが自動的に識別する方法はないと考えてください。

    キャンセル

  • 2018/10/10 02:55

    そもそも、test.pyの中身って何なのですか?参考までに質問に追記していただけると助かります。

    キャンセル

  • 2018/10/10 09:10

    すみません、もしかしたら、私が何かしら誤解している可能性がある気もしてきました。その誤解もときたいという思いがあります。上記に test.pyの中身を追記しました。

    キャンセル

  • 2018/10/10 11:07

    うーん。何がしたいのかはやはり謎です。

    > stating.py及び、 production.pyはそれぞれ、環境ごとの環境変数がかかれている。
    とありますが、
    TESTING = True
    DEBUG = True
    のような大文字表記の変数のことを「環境変数」と言っていますか?これは環境変数ではないです。
    環境変数は実行しているOSが管理しているもので実行プロセスごとに設定されており、Pythonからは os.environ でアクセスします。

    もしかしてこういうことがしたかったんでしょうか。
    https://qiita.com/ukisoft/items/8912d0a66151609d9ff9

    キャンセル

  • 2018/10/10 15:50

    はい、そのURLに記載しているようなことがやりたいことです。

    キャンセル

  • 2018/10/10 15:50 編集

    そのURLに記載しているやり方だと、読み込む settings のconfigを手動でTerminalから打って変えているように見ますが、これ以外の方法はないものでしょうか?

    キャンセル

  • 2018/10/10 16:24

    手で打って変えているのは Heroku アプリケーションの設定値(環境変数)です。Herokuの場合は基本的にこの手段しかありません。
    Herokuなどのサービス設計を理解する上で参考になる 12-Factor App という資料のURLを置いておきます。
    https://12factor.net/ja/

    キャンセル

  • 2018/10/10 17:52 編集

    herokuは使わないんですよね。ありがとうございます。dockerの場合は普通どうするものでしょうか?

    キャンセル

  • 2018/10/11 10:16

    Dockerを使う場合、test, staging, production でDockerイメージは共通にすべきだと思います。
    docker run の -e オプションで環境変数が設定可能なので、そちらを利用するといいと思います。

    キャンセル

  • 2018/10/18 11:29

    返事、遅くなり、すみません。ありがとうございます。腑に落ちました。

    キャンセル

+1

create_appメソッドの中で、渡された名前をもとにtest.py/staging.py/production.pyのいずれかのモジュールをインポートして処理したいということでしょうか。

例えば、

# coding: utf-8
# test.py

def call_my_name():
    print('test')
# coding: utf-8
# staging.py

def call_my_name():
    print('staging')
# coding: utf-8
# production.py

def call_my_name():
    print('production')

だとします。

 方法1: モジュール名ではなく、モジュール自体を渡す

def create_app(module):
    module.call_my_name()

if name == 'test':
    import test as conf_module
elif name == 'staging':
    import staging as conf_module
else:
    import production as conf_module

create_app(conf_module)

 方法2: importlibを使う。

import importlib

def create_app(name):
    m = importlib.import_module(name)
    m.call_my_name()

if name == 'test':
    create_app('test')
elif name == 'staging':
    create_app('staging')
else:
    create_app('production')

3つしかないのであれば、前者の方法でいいと思います。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/10/09 23:52

    ありがとうございます。私の言葉足らずで少し誤解招いているかもしれません。

    create_appメソッドの中で、渡された名前をもとに

    ではありません。

    また、create_app内で呼ばれ値によってでもありません。

    実行される環境ごとに読み込むconfigを変えたいです。つまり、おそらく__name__の値ごとに異なるかなと思っています。
    test.pyはローカル環境、staging.pyは、docker上かつGAE、production.pyはdocker 上かつGKEです。

    キャンセル

  • 2018/10/10 09:10 編集

    GAEもGKEも知りませんが、結局のところmatherさんのやり方で解決するのではないですか。
    私もmatherさんの回答で解決しなさそうなので回答しましたが、コピー一回で解決するのであればこんな馬鹿らしいやり方はしません。(知識として知っておくといいと思って回答しましたが)

    そもそも、「__name__」が何なのか、理解していますか?
    (「おそらく」という話をすれば、私は関係ないと思います。あくまで「おそらく」ですが)

    キャンセル

+1

>>test.py/staging.py/production.pyのそれぞれ3つのconfigファイルがあります。

各環境に、この3ファイルのいずれか1つがある、ということであれば、各々のファイルの存在チェックを行って環境の特定をしつつ、katsukoさんのコードの要領でimportするファイルを切替える方法が無くもないです。
(が、私であればその方法は採りません。matherさんの書かれている方法を採ります)

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

同じタグがついた質問を見る

  • Python 3.x

    10228questions

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

  • Flask

    362questions

    FlaskはPython用のマイクロフレームワークであり、Werkzeug・Jinja 2・good intentionsをベースにしています。