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

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

新規登録して質問してみよう
ただいま回答率
85.48%
Python 3.x

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

Python

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

Q&A

解決済

2回答

2149閲覧

Python プロジェクトにおける適切な config の管理方法

Demerara

総合スコア397

Python 3.x

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

Python

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

0グッド

1クリップ

投稿2022/12/21 08:49

編集2022/12/21 09:01

前提

Python で CLI ツールを開発しています。開発環境は Windows です。

プログラムの規模が大きくなり、複数のファイルに分けてソースコードを管理するようになりました。しかしながら、何分大きなプロジェクトが初めての経験で色々戸惑っております。

実現したいこと

コードの可読性と管理のしやすさに重点を置いた場合の適切な設定(config)の保持方法を知りたいです。

dataclass より CONSTANT で保持した方がいいとか、json データなら json で保持すべき等のアドバイスが欲しいです。

ユーザーによって編集できるような設定ファイルではなく、あくまでソースコードの中の話です。

設定ファイルうんぬんというより、Python におけるプロジェクト構造のベストプラクティスを知りたいのかも知りません。皆バラバラなので…。

発生している問題・エラーメッセージ

問題は発生していません。

該当のソースコード

今現在の私の設定の保持方法です。わかりやすい例でヘッダーを出していますが、他にも固定長のリストやタプルを保持することがあります。

config.py というファイルを作成し、dataclassfrozen を使うことでデータの安全性を確保しているつもりです。

python

1"""config.py""" 2 3from dataclasses import dataclass, field 4 5 6@dataclass(slots=True, frozen=True) 7class Config: 8 HEADER: dict[str, str] = field( 9 default_factory=lambda: { 10 "Accept": "image/jpeg,image/jpg,image/png,image/webp", 11 "Accept-Encoding": "gzip, deflate, br", 12 "Accept-Language": "en-US,en;q=0.5", 13 "Cache-Control": "no-cache", 14 "Connection": "keep-alive", 15 "DNT": "1", 16 "Pragma": "no-cache", 17 "User-Agent": ( 18 "Mozilla/5.0 (Windows NT 10.0; rv:108.0) " 19 "Gecko/20100101 Firefox/108.0" 20 ), 21 } 22 ) 23

しかしながら、そもそも設定内容を dataclass で保持し、エクスポートして使うことが本当に正しいのかよくわかりません。

純粋に CONSTANT でいいのでは?とも思います。

python

1"""constant.py""" 2 3HEADER: dict[str, str] = { 4 "Accept": "image/jpeg,image/jpg,image/png,image/webp", 5 "Accept-Encoding": "gzip, deflate, br", 6 "Accept-Language": "en-US,en;q=0.5", 7 "Cache-Control": "no-cache", 8 "Connection": "keep-alive", 9 "DNT": "1", 10 "Pragma": "no-cache", 11 "User-Agent": ( 12 "Mozilla/5.0 (Windows NT 10.0; rv:108.0) " 13 "Gecko/20100101 Firefox/108.0" 14 ), 15} 16

別のファイルで読み込む場合、config.py なら、

python

1"""helper.py""" 2 3import httpx 4from .config import Config 5 6config = Config() 7 8 9@dataclass(slots=True) 10class Downloader: 11 async def fetch(self, url: str) -> str: 12 async with httpx.AsyncClient( 13 headers=config.HEADER, 14 http2=True, 15 timeout=httpx.Timeout( 16 timeout=5.0, connect=5.0, read=5.0, write=5.0, pool=5.0 17 ), 18 ) as client: 19 res: httpx.Response = await client.get(url) 20 res.raise_for_status() 21 return res.text() 22

constant.py なら、

python

1"""helper.py""" 2 3import httpx 4from .constant import HEADER 5 6 7@dataclass(slots=True) 8class Downloader: 9 async def fetch(self, url: str) -> str: 10 async with httpx.AsyncClient( 11 headers=HEADER, 12 http2=True, 13 timeout=httpx.Timeout( 14 timeout=5.0, connect=5.0, read=5.0, write=5.0, pool=5.0 15 ), 16 ) as client: 17 res: httpx.Response = await client.get(url) 18 res.raise_for_status() 19 return res.text() 20

これだとちょっとわかりづらいので、import constant として、constant.HEADER とした方がコードが読みやすいでしょうか。

そもそも初めは、同一ファイルにクラスのプロパティとして保持していました。そのうち格納したい値が増えて、ごちゃごちゃしてきたのでファイルを分けるようになりました。

試したこと

今回の例の場合、データ型が json のため、純粋な json ファイルで保持し、デコードしてソースコードで利用するという方法もあります。

json

1{ 2 "Accept": "image/jpeg,image/jpg,image/png,image/webp", 3 "Accept-Encoding": "gzip, deflate, br", 4 "Accept-Language": "en-US,en;q=0.5", 5 "Cache-Control": "no-cache", 6 "Connection": "keep-alive", 7 "DNT": "1", 8 "Pragma": "no-cache", 9 "User-Agent": "Mozilla/5.0 (Windows NT 10.0; rv:108.0) Gecko/20100101 Firefox/108.0" 10}

加えて、一般的な設定ファイル:iniyamltoml 等もデコード処理が入るため、速度面を考慮すると純粋な Python ファイルの方がいいような気もします。その辺はよくわかりません。

まとめ

ここまでの内容をまとめると、config は、

  1. クラス内で直接保持
  2. 別のクラスで保持
  3. コンスタントで保持
  4. データ毎のネイティブな保持

のうち、どの方法がより可読性が高く管理がしやすいでしょうかというのが今回の質問です。

実際に開発されている方はどのように考えどのような理由の元に各データを配置・管理しているのかも知りたいです。

補足情報(FW/ツールのバージョンなど)

  • Windows 11 home 22H2
  • Python 3.11.1
  • Poetry 1.3.1
  • VSCode 1.7.2

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

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

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

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

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

yuma.inaura

2022/12/21 08:58

>これは json データに限りるので、他にもリスト型のデータがあった場合、設定ファイルを分けることになってしまいます JSONでも配列は使えるのでそれで良いんじゃないでしょうか?
Demerara

2022/12/21 08:59

なるほど、そうですね。うっかりしてました。再編集します。
guest

回答2

0

ベストアンサー

ライトに書くなら yaml。json はコメント書けないし末尾カンマがめんどくさい。
ただ yaml も json も単なるデータであるので、初期値設定とかエラーチェックとか post_init とかしたいのなら dataclass もよいのでは (つまり用途が異なる)

と思います。

投稿2022/12/21 13:43

68user

総合スコア2005

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

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

Demerara

2022/12/22 11:57

回答ありがとうございます。 そうなんですよね、json は色々不便なんで好きになれません。 自分は場合によって、pydantic でバリデーションチェックしたりするので、そういう場合は dataclass 等を使う理由にもなるということですね。参考になります。
guest

0

可読性という意味から、最近は設定ファイルは yamlにしています。

一般的な設定ファイル:ini、yaml、toml 等もデコード処理が入るため、速度面を考慮すると純粋な Python ファイルの方がいいような気もします。

設定が数GBとかでなければ、速度のことを気にする必要はないと思います。設定なので、何度も読むわけでもないでしょうし。

投稿2022/12/21 09:29

TakaiY

総合スコア12765

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

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

Demerara

2022/12/21 09:39

回答ありがとうございます。 速度は気にしなくていいんですね。 可読性という点から、yaml にしているんですね。参考にします。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問