web-dev-qa-db-ja.com

Pythonファイルを構成ファイルとして使用するのはどれほど悪いことですか?

私は、アプリケーションの構成に常に[〜#〜] json [〜#〜]ファイルを使用してきました。たくさんのJavaをコーディングしたときから使い始めましたが、現在は主にサーバー側とデータサイエンスに取り組んでいますPython開発であり、[〜#〜] json [〜#〜]は、これ以上の正しい方法です。

セロリが実際のPythonファイルを構成に使用するのを見てきました。最初はそれについて懐疑的でした。しかし、構成に単純なPythonデータ構造を使用するという考えが始まっています私に成長するために。いくつかのプロ:

  • データ構造は、私が通常コーディングしているものと同じになります。そのため、考え方を変える必要はありません。
  • 私のIDE(PyCharm)は、設定とコードの関係を理解し​​ています。 Ctrl + B 構成とコードの間を簡単に移動できるようにします。
  • IMO不要なstrict[〜#〜] json [〜#〜]を使用する必要はありません。二重引用符、末尾のカンマ、コメントはありません。
  • 作業中のアプリケーションでテスト構成を記述し、変換やJSON解析を行わなくても、構成ファイルに簡単に移植できます。
  • 本当に必要な場合は、構成ファイルで非常に簡単なスクリプトを作成することができます。 (ただし、これは非常に限られたものです。)

だから、私の質問は:切り替えた場合、どのようにして自分を足で撃っているのですか?

熟練していないエンドユーザーが構成ファイルを使用することはありません。構成ファイルへの変更は現在Gitにコミットされており、継続的デプロイメントの一部としてサーバーにロールアウトされます。緊急の場合、または開発中の場合を除き、手動による構成変更はありません。

(私は[〜#〜] yaml [〜#〜]と考えましたが、それについて何かが私を苛立たせています。したがって、今のところ、アメリカのテーブル。)

設定ファイルの代わりにスクリプト言語を使用すると、一見すると見栄えが良くなります。その言語の全機能を利用でき、単純にeval()またはimportできます。実際には、いくつかの落とし穴があります。

  • それは学習する必要があるプログラミング言語です。設定を編集するには、この言語を十分に理解している必要があります。設定ファイルは通常、間違いを起こしにくい、より単純な形式です。

  • これはプログラミング言語です。つまり、構成のデバッグが難しくなる可能性があります。通常の構成ファイルでは、それを見て、各プロパティにどのような値が提供されているかを確認します。スクリプトを使用する場合、値を表示するには、最初にスクリプトを実行する必要がある可能性があります。

  • これはプログラミング言語であるため、構成と実際のプログラムを明確に区別することは困難です。この種の拡張性が必要な場合もありますが、その時点で、おそらく実際のプラグインシステムを探していることになります。

  • これはプログラミング言語です。つまり、configはプログラミング言語が実行できるすべてのことを実行できます。したがって、言語の柔軟性の多くを無効にするサンドボックスソリューションを使用しているか、構成の作成者に高い信頼を置いています。

したがって、ツールの対象者が開発者である場合は、構成にスクリプトを使用しても問題ない可能性があります。 Sphinx configまたはPythonプロジェクトのsetup.py。実行可能な構成を持つ他のプログラムは、BashのようなシェルやVimのようなエディターです。

設定に多くの条件付きセクションが含まれている場合、またはコールバック/プラグインを提供している場合は、設定にプログラミング言語を使用する必要があります。 eval()の代わりにスクリプトを直接使用すると、一部の構成フィールドがデバッグしやすくなる傾向があります(スタックトレースと行番号を考えてください!)。

構成が非常に反復的で構成を自動生成するスクリプトを作成している場合は、プログラミング言語を直接使用することも良い考えです。しかし、おそらく構成のより良いデータモデルは、そのような明示的な構成の必要性を取り除くことができるでしょうか?たとえば、後で展開するプレースホルダーを構成ファイルに含めることができると便利です。ときどき見られる別の機能は、優先順位が異なる複数の設定ファイルで、互いにオーバーライドできますが、それ自体にいくつかの問題があります。

ほとんどの場合、INIファイル、Javaプロパティファイル、またはYAMLドキュメントが構成に適しています。複雑なデータモデルの場合、XMLも既に説明したように、JSONは、データを交換するための優れたフォーマットですが、人間が編集できる構成ファイルとしては不適切な側面があります。

94
amon

amon's answer のすべてに+1します。これを追加したい:

Pythonコードを構成言語として初めて使用するときは、別の言語で記述されたコード内から同じ構成をインポートするときは後悔します。たとえば、プロジェクトの一部であるコードとC++またはRubyまたは他の何かで構成をプルする必要がある場合は、Pythonインタプリタをライブラリとしてリンクするか、構成を解析する必要があります。 Pythonコプロセス。どちらも扱いにくい、難しい、またはオーバーヘッドが大きい。

今日この構成をインポートするすべてのコードはPythonで記述されている可能性があり、これは明日も当てはまると思うかもしれませんが、本当に知っていますか?

構成ではロジック(静的データ構造以外のもの)を控えめに使用するのが良いと言っていましたが、それが少しでもあると、将来、元に戻すことが難しくなるでしょう。宣言的な構成ファイルに戻ることができます。

[〜#〜] edit [〜#〜]記録:複数の人々がこの回答について、プロジェクトの可能性または可能性についてコメントしました別の言語で完全に書き直されることに成功するでしょう。完全な下位互換性のある書き直しがおそらくめったに見られないと言うのは公正です。私が実際に考えていたのは、同じプロジェクトのさまざまな言語で書かれている(そして同じ構成にアクセスする必要がある)ことです。たとえば、速度を上げるためにC++でスタックを提供し、Pythonでバッチデータベースをクリーンアップし、いくつかのシェルスクリプトを接着剤として使用します。だから、その場合も考えてみてください:)

51
Celada

他の答えはすでに非常に良いです。実際の使用例をいくつかのプロジェクトで紹介します。

長所

彼らはほとんどすでにスペルアウトされています:

  • Pythonプログラムの場合、解析は簡単です(eval)。これは、より複雑なデータ型でも自動的に機能します(プログラムには、幾何学的ポイントと変換があります。 、repr/eval);を通じて正常にダンプ/ロードされます。
  • ほんの数行のコードで「偽の構成」を作成するのは簡単です。
  • jSONよりも構造が優れており、IMOの構文がはるかに優れています(コメントがあるだけで、辞書のキーを二重引用符で囲む必要がないので、読みやすさが大幅に向上します)。

短所

  • 悪意のあるユーザーは、メインプログラムで実行できることを何でも実行できます。私はこれほどの問題は考慮していません。通常、ユーザーが構成ファイルを変更できる場合、ユーザーはアプリケーションが実行できることは何でもできるためです。
  • Pythonプログラムに参加していない場合は、問題が発生しました。構成ファイルのいくつかは元のアプリケーションに対して非公開のままでしたが、特に1つは複数のさまざまなプログラム、そのほとんどは現在C++にあり、Python reprの不適切に定義された小さなサブセット用のハッキングされたパーサーがあります。これは明らかに悪いことです。 。
  • プログラムがPythonのままである場合でも、Pythonバージョンを変更できます。たとえば、アプリケーションがPython 2; to Python 3-残念ながら、あなたはすべてのコードをテストしていません本当に-あなたはすべての設定ファイルを持っていますPython 2用に書かれていて、実際には制御できません。古い互換性モードを提供して、古い構成ファイル(つまりPython 2インタプリタ!
  • Pythonを使用している場合でも、コードからの構成ファイルのmodifyingは実際の問題です。なぜなら、コードの変更は簡単ではないためです。 特に豊富な構文を持ち、LISPまたは類似のコードではないコード。私たちのプログラムの1つには、元々手作業で記述されたPythonの構成ファイルがありますが、後でソフトウェアを介して操作すると便利です(特定の設定は、のリストです) wayGUIを使用して並べ替えるのが簡単です)。これは大きな問題です。

    • 解析→AST→書き換えのラウンドトリップを実行するだけでも 自明ではない (提案されたソリューションの半分が後で「廃止され、使用されず、すべてのケースで機能しない」とマークされることに気付くでしょう) ;
    • 動作したとしても、ASTは低すぎるレベルです。一般的に、の結果を操作することに興味があります。ファイルにもたらされたステップではなく、ファイルで実行された計算。
    • これは、目的の値を単に編集することはできないという単純な事実をもたらします。なぜなら、それらの値は、コードを通じて理解/操作できない複雑な計算によって生成される可能性があるためです。

    これをJSON、INIまたは(God forbid!)XMLと比較してください。この場合、メモリ内の表現は常に編集でき、データを失うことなく書き戻すことができます(XML、ほとんどのDOMパーサーが保持できる場所)テキストノードとコメントノードの空白)、または少なくとも一部のフォーマットが失われます(JSON。フォーマット自体では、読み取っている生データ以外の多くは許可されません)。


したがって、いつものように、明確な解決策はありません。この問題に関する私の現在の方針は次のとおりです。

  • 構成ファイルが次の場合:

    • 確かにPythonアプリケーションであり、それにプライベートです-他の人と同じように、他の誰もそれから読み込もうとはしません。
    • 手書き;
    • 信頼できるソースからのもの;
    • ターゲットアプリケーションのデータ型を使用することは非常に重要です。

    a Python filemayは有効なアイデアかもしれません。

  • 代わりに:

    • 他のアプリケーションから読み取られる可能性があります。
    • このファイルがアプリケーションによって編集されている可能性があります。おそらく私のアプリケーション自体ですらあります。
    • 信頼できないソースから提供されています。

    「データのみ」のフォーマットの方が良いかもしれません。

単一の選択を行う必要はないことに注意してください。最近、両方のアプローチを使用するアプリケーションを作成しました。最初の設定がほとんど変更されていないファイルがあり、ニースPythonボーナスがあるという利点がある手書きの設定と、UIから編集された構成用のJSONファイルがあります。

21
Matteo Italia

主な質問は次のとおりです:構成ファイルをチューリング完全言語で記述しますか(Python is)など)?必要な場合は、 Guile または Lua のようないくつかのother(Turing complete)スクリプト言語を埋め込む(「より単純な」と認識される可能性があるためPython is; Extending&Embedding Python )の章を読んだり、埋め込んだりするために、これについては説明しません(他の回答-eg- Amonによって -詳細に説明しました)アプリケーションにスクリプト言語を組み込むことはmajorアーキテクチャ上の選択であることに注意してください。あなたは非常に早いを考慮する必要があります;私は本当にその選択を後ですることをお勧めしません!

「スクリプト」を介して構成可能なプログラムのよく知られた例は、 GNU emacs エディター(またはおそらく AutoCAD 独自のレルム)です。したがって、スクリプトを受け入れる場合、一部のユーザーは最終的にその機能を広範囲に使用して-そしておそらく虐待-を使用して、数千行のスクリプトを作成します。したがって、十分に優れたスクリプト言語を選択することが重要です。

ただし(少なくともPOSIXシステムでは)設定「ファイル」を初期化時に動的に計算する(もちろん、健全な構成の負担をシステム管理者またはユーザーに任せます;実際には、それは構成textであり、ファイルまたはコマンドからのものです)。そのためには、単にconvention(およびdocumentit)という設定ファイルのパスを、 _!_または_|_は、実際にはシェルコマンドであり、 パイプライン として読み取ることができます。これにより、ユーザーは最も慣れ親しんでいる「プリプロセッサ」または「スクリプト言語」を選択できます。

(動的に計算された構成を受け入れる場合は、セキュリティの問題についてユーザーを信頼する必要があります)

したがって、初期化コードでは、mainは(たとえば)_--config_ argumentconfargを受け入れて、そこから_FILE*configf;_を取得します。その引数が_!_で始まる場合(つまり、_(confarg[0]=='!')_ ....)の場合、configf = popen(confarg+1, "r");を使用し、pclose(configf);でパイプを閉じます。そうでない場合は、configf=fopen(confarg, "r");を使用し、そのファイルをfclose(configf);で閉じます(エラーチェックを忘れないでください)。 pipe(7)popen(3)fopen(3) を参照してください。 Pythonについてコーディングされたアプリケーションの場合 os.popen について読む...など).

(_!foo.config_という名前の構成ファイルを渡して、_./!foo.config_を渡して上記のpopenトリックをバイパスしたい、変なユーザー向けのドキュメント)

ところで、そのようなトリックは便利です(上級ユーザーがシェルスクリプトをgenerategenerate(---)generatefile)。ユーザーがバグを報告したい場合は、generated構成ファイルを送信する必要があります...

また、初期化時に使用およびロードする機能を備えたアプリケーションを設計 pluginsすることもできます。 dlopen(3) を使用します(そのプラグインについてユーザーを信頼する必要があります)。繰り返しますが、これは非常に重要なアーキテクチャ上の決定です(そしてdefineし、かなり安定したものを提供する必要があります [〜#〜] api [〜#〜] これらのプラグインとアプリケーションに関する規約)。

Pythonのようなスクリプト言語でコーディングされたアプリケーションの場合、 eval または exec または同様のプリミティブのプログラム引数を受け入れることもできます。繰り返しますが、 セキュリティの問題はの懸念事項です(詳細)ユーザー。

構成ファイルのテキスト形式について(生成されるかどうかに関係なく)ドキュメント化well(そして特定の形式の選択は重要ではありませんただし、ユーザーがその中に-スキップされた-コメントを入れることができるようにすることをお勧めします)。 JSONを使用することができます(JSONパーサーがeolまたは_//_..._/*_ ...)までの通常の_*/_でコメントを受け入れてスキップするか、YAML、XML、または= INIまたは独自のもの。構成ファイルの解析はかなり簡単です(そして、そのタスクに関連する多くのライブラリがあります)。

amon's answer に追加して、代替案を検討しましたか? JSONはおそらくあなたが必要とする以上のものですが、Pythonファイルはおそらく上記の理由により将来的に問題を引き起こすでしょう。

ただし、Pythonには、すべてのニーズを満たす非常に単純な構成言語用の構成パーサーがすでにあります。 ConfigParser module は、単純な構成言語を実装します。

2
CodeMonkey

TCLで構成ファイルが記述されている よく知られたソフトウェア で長い間作業してきたので、アイデアは新しいものではありません。言語を知らないユーザーでも、単一のset name valueステートメントを使用して簡単な設定ファイルを作成/編集できる一方で、より上級のユーザーや開発者がこれを使用して高度なトリックを実行できるため、これは非常にうまくいきました。

「構成ファイルのデバッグが難しくなる可能性がある」とは私には関係ないと思います。アプリケーションがユーザーにスクリプトの作成を強制しない限り、ユーザーは常に構成ファイルで単純な割り当てを使用できます。これは、JSONやXMLと比較して、正しく取得することがほとんど困難です。

見た目ほど悪くはありませんが、設定の書き換えは問題です。任意のコードを更新することは不可能ですが、ファイルから設定をロードし、それを変更して保存することはできます。基本的に、読み取り専用ではない構成ファイルでスクリプトを実行すると、保存された後のset name valueステートメントの同等のリストが作成されます。これが発生する良いヒントは、ファイルの先頭にある「編集しない」コメントです。

考慮すべきことの1つは、sedなどの単純な正規表現ベースのツールでは構成ファイルを確実に読み取ることができないことですが、私が理解している限り、これは現在のJSONファイルには当てはまりません。失うものはあまりありません。

設定ファイルを実行するときは、適切な sandboxing テクニックを使用していることを確認してください。

1

ここで他の良い答えのすべての有効なポイント(すごい、チューリング完全な概念についても言及しました)に加えて、実際にPythonファイルを構成として使用しないことには、いくつかの確かな理由があります。 Pythonのみのプロジェクトで作業しているときでも。

  1. Pythonソースファイル内の設定は、技術的には読み取り専用のデータファイルではなく、実行可能なソースコードの一部です。このルートを使用する場合、通常はimport config、そのような「便利さ」は、おそらく最初にPythonファイルをconfigとして使用することから始めた主な理由の1つでした。今では、config.pyをコミットする傾向がありますそうしないと、エンドユーザーが初めてプログラムを実行しようとすると、混乱するImportErrorが発生します。

  2. 実際にそのconfig.pyをリポジトリにコミットすると仮定すると、チームメンバーはおそらく環境ごとに異なる設定を持つことになります。想像してみてください いつかどういうわけか あるメンバーが自分のローカル構成ファイルを誤ってリポジトリにコミットしました。

  3. 最後に、プロジェクトの構成ファイルにパスワードを含めることができます。 (これ自体は議論の余地のある慣行ですが、とにかく起こります。)そして、構成ファイルがリポジトリに存在する場合、資格情報をパブリックリポジトリにコミットするリスクがあります。

これで、ユニバーサルJSON形式などのデータのみの構成ファイルを使用すると、上記の3つの問題すべてを回避できます。これは、ユーザーに独自のconfig.jsonを考え出して、プログラムにフィードするよう依頼できるためです。

PS:JSONには多くの制限があることは事実です。 OPによって言及された制限の2つは、いくつかの創造性によって解決できます。

1
RayLuo