ホームページ >バックエンド開発 >Python チュートリアル >楽な Python 設定ファイル バージョン 1 に向けて

楽な Python 設定ファイル バージョン 1 に向けて

Susan Sarandon
Susan Sarandonオリジナル
2024-12-02 14:55:19790ブラウズ

導入

前の記事で述べたように、単純化されたバージョンにはスケーラビリティ、保守性、拡張性などの問題が山積しています。

Version Ø からの簡単な拡張は、Python 設定の詳細をプロパティ クラスの背後に隠そうとすることです。 つまり、開発者がプロ​​パティ set および get の呼び出しを行うだけでプロパティ値を取得して保持できるようにするプロパティのセットを公開する疑似データ クラスを実装します。

メンテナの観点から、この実装は次の機能をサポートする必要があります。

  1. 構成セクションが欠落している場合に、構成セクションの自動作成を許可します
  2. プロパティ値が欠落している場合、プロパティ値の自動作成を許可します
  3. プロパティは、リードスルーとライトスルーの両方として実装する必要があります。
  4. アプリケーションがアプリケーション全体でこのクラスをインスタンス化するときに、上記の起動コストを回避するには、このクラスをシングルトンにする必要があります。

クラスの代表

次の UML クラス図は、導入部の要件を満たすクラスを示しています。 ConfiguratonProperties クラスは、保護されたメソッド .createMissingSections および .createMissingKeys

を使用して要件 1 と 2 を満たします。

Towards Effortless Python Configuration Files Version 1

実装の作成

欠落しているセクションを作成する

次のコードは実装を示しています。 追加のセクションでは、このメソッドのコードを更新する必要があることに注意してください

SECTION_GENERAL:  str = 'General'
SECTION_DATABASE: str = 'Database'

def _createMissingSections(self):
    """
    Create missing sections.  Add additional calls for
    each defined section
    """
    self._createMissingSection(SECTION_GENERAL)
    self._createMissingSection(SECTION_DATABASE)

欠落しているセクションのコードは次のとおりです。

def _createMissingSection(self, sectionName: str):
    """
    Only gets created if it is missing
    Args:
        sectionName: The potential section to create
    """
    hasSection: bool = self._configParser.has_section(sectionName)
    self.logger.info(f'hasSection: {hasSection} - {sectionName}')
    if hasSection is False:
        self._configParser.add_section(sectionName)

不足しているキーを作成する

次のコードは実装を示しています。 繰り返しますが、追加のセクションを追加する場合、開発者は新しいセクションに追加のループを追加する必要があることに注意してください。

GENERAL_PREFERENCES: Dict[str, str] = {
    'debug':    'False',
    'logLevel': 'Info'
}

DATABASE_PREFERENCES: Dict[str, str] = {
    'dbName': 'example_db',
    'dbHost': 'localhost',
    'dbPort': '5432'
}

def _createMissingKeys(self):
    """
    Create missing keys and their values.  Add additional calls for
    each defined section.
    """
    for keyName, keyValue in GENERAL_PREFERENCES.items():
        self._createMissingKey(sectionName=SECTION_GENERAL, keyName=keyName, defaultValue=keyValue)
    for keyName, keyValue in DATABASE_PREFERENCES.items():
        self._createMissingKey(sectionName=SECTION_DATABASE, keyName=keyName, defaultValue=keyValue)

不足しているキーコードは次のとおりです。 不足しているキーはすぐに永続化されることに注意してください。

def _createMissingKey(self, sectionName: str, keyName: str, defaultValue: str):
    """
    Only gets created if it is missing.  The configuration file is updated
    immediately for each missing key and its value

    Args:
        sectionName:   The section name where the key resides
        keyName:       The key name
        defaultValue:  Itsß value
    """
    if self._configParser.has_option(sectionName, keyName) is False:
        self._configParser.set(sectionName, keyName, defaultValue)
        self._saveConfiguration()

クラスのプロパティ

要件 3 のサンプル実装は次のとおりです。

文字列のプロパティ

プロパティを設定してすぐに永続化することにより、プロパティを設定すると構成ファイルにライトスルーが行われることに注意してください。 セットされたプロパティを即座に書き込む方法により、プロパティの読み取りは事実上リードスルーとなります。

@property
def dbName(self) -> str:
    return self._configParser.get(SECTION_DATABASE, 'dbName')

@dbName.setter
def dbName(self, newValue: str):
    self._configParser.set(SECTION_DATABASE, 'dbName', newValue)
    self._saveConfiguration()

整数のプロパティ

整数プロパティは、.getint メソッドを使用して値を取得します。 プロパティを設定するとき、開発者はそれを手動で文字列に変換する必要があります。

@property
def dbPort(self) -> int:
    return self._configParser.getint(SECTION_DATABASE, 'dbPort')

@dbPort.setter
def dbPort(self, newValue: int):
    self._configParser.set(SECTION_DATABASE, 'dbPort', str(newValue))
    self._saveConfiguration()

ブール値のプロパティ

ブール型プロパティは、.getboolean メソッドを使用して値を取得します。 プロパティを設定するとき、開発者はそれを手動で文字列に変換する必要があります。

SECTION_GENERAL:  str = 'General'
SECTION_DATABASE: str = 'Database'

def _createMissingSections(self):
    """
    Create missing sections.  Add additional calls for
    each defined section
    """
    self._createMissingSection(SECTION_GENERAL)
    self._createMissingSection(SECTION_DATABASE)

列挙プロパティ

この記事では列挙プロパティについては説明しません。 それらを永続化するには、名前または値を使用する 2 つの方法があります。 各メカニズムでは、値を列挙型に逆シリアル化するために若干異なる方法が必要です。

プロパティへのアクセスと変更

次のコード スニペットは、プロパティにアクセスして変更する方法を示しています。

def _createMissingSection(self, sectionName: str):
    """
    Only gets created if it is missing
    Args:
        sectionName: The potential section to create
    """
    hasSection: bool = self._configParser.has_section(sectionName)
    self.logger.info(f'hasSection: {hasSection} - {sectionName}')
    if hasSection is False:
        self._configParser.add_section(sectionName)

上記のスニペットは次の出力を生成します

GENERAL_PREFERENCES: Dict[str, str] = {
    'debug':    'False',
    'logLevel': 'Info'
}

DATABASE_PREFERENCES: Dict[str, str] = {
    'dbName': 'example_db',
    'dbHost': 'localhost',
    'dbPort': '5432'
}

def _createMissingKeys(self):
    """
    Create missing keys and their values.  Add additional calls for
    each defined section.
    """
    for keyName, keyValue in GENERAL_PREFERENCES.items():
        self._createMissingKey(sectionName=SECTION_GENERAL, keyName=keyName, defaultValue=keyValue)
    for keyName, keyValue in DATABASE_PREFERENCES.items():
        self._createMissingKey(sectionName=SECTION_DATABASE, keyName=keyName, defaultValue=keyValue)

結論

この記事のソースコードはここにあります。 サポートクラス SingletonV3 はこちら

実装の結果は、コードの消費者として最初は満足でした。 型付きプロパティを取得および設定することができました。 ただし、コードの管理者として、新しいセクションや新しいプロパティを追加するたびに、コードのデータ構造とコード ループを手動で更新する必要がありました。 さらに、このことから実際に得られたのは、さまざまなアプリケーションで新しい構成プロパティが必要になったときに使用するメカニズム/パターンだけです。

利点

  • アプリケーションのプロパティに簡単にタイプセーフにアクセスできます
  • アプリケーションのさまざまな部分でシングルトンを呼び出すことで、アプリケーションのどの部分が値を変更したかに関係なく、プロパティへの一貫した信頼性の高いアクセスが提供されました

短所

  • 新しいプロパティを追加するための更新は面倒でした
  • 定型コードがたくさんあります
  • さまざまなアプリケーション間での再利用はできません。 要するに、テンプレートがあっただけです

利点を維持しながら、私が列挙した欠点に対処するための代替実装を文書化した次の投稿を参照してください。

以上が楽な Python 設定ファイル バージョン 1 に向けての詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。