Heim >Backend-Entwicklung >Python-Tutorial >Auf dem Weg zu mühelosen Python-Konfigurationsdateien Version 1
Wie im vorherigen Artikel erwähnt, ist die vereinfachte Version voller Probleme, einschließlich Skalierbarkeit, Wartbarkeit und Erweiterbarkeit.
Eine einfache Erweiterung von Version Ø besteht darin, zu versuchen, die Python-Konfigurationsdetails hinter einer Eigenschaftsklasse zu verbergen. Das bedeutet, dass eine Pseudodatenklasse implementiert wird, die eine Reihe von Eigenschaften verfügbar macht, die es einem Entwickler ermöglichen, einfach Eigenschaftsaufrufe set und get auszuführen, um Eigenschaftswerte abzurufen und beizubehalten.
Aus Sicht des Betreuers sollte diese Implementierung die folgenden Funktionen unterstützen.
Das folgende UML-Klassendiagramm beschreibt eine Klasse, die die Anforderungen in der Einleitung erfüllen würde. Die ConfiguratonProperties-Klasse erfüllt die Anforderungen 1 und 2 mit den geschützten Methoden .createMissingSections und .createMissingKeys
Der folgende Code zeigt die Implementierung. Beachten Sie, dass für zusätzliche Abschnitte Codeaktualisierungen dieser Methode erforderlich sind
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)
Der fehlende Abschnittscode lautet wie folgt.
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)
Der folgende Code zeigt die Implementierung. Beachten Sie erneut, dass der Entwickler beim Hinzufügen eines zusätzlichen Abschnitts eine zusätzliche Schleife für den neuen Abschnitt hinzufügen muss.
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)
Der fehlende Schlüsselcode lautet wie folgt. Beachten Sie, dass alle fehlenden Schlüssel sofort beibehalten werden.
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()
Beispielimplementierungen für Anforderung 3 folgen.
Beachten Sie, dass beim Festlegen einer Eigenschaft ein Durchschreiben in die Konfigurationsdatei erfolgt, indem die Eigenschaft festgelegt und sofort beibehalten wird. Leseeigenschaften werden effektiv durchgelesen, da wir festgelegte Eigenschaften sofort schreiben.
@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()
Integer-Eigenschaften verwenden die .getint-Methode, um den Wert abzurufen. Beim Festlegen der Eigenschaft muss der Entwickler sie manuell in eine Zeichenfolge konvertieren.
@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()
Boolesche Eigenschaften verwenden die .getboolean-Methode, um ihren Wert abzurufen. Beim Festlegen der Eigenschaft muss der Entwickler sie manuell in eine Zeichenfolge konvertieren.
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)
Auf Aufzählungseigenschaften werde ich in diesem Artikel nicht eingehen. Es gibt zwei Möglichkeiten, sie beizubehalten: nach ihrem Namen oder nach ihrem Wert. Jeder Mechanismus erfordert eine etwas andere Methode, um die Werte wieder in einen Aufzählungstyp zu deserialisieren.
Der folgende Codeausschnitt zeigt, wie auf die Eigenschaften zugegriffen und diese geändert werden.
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)
Das obige Snippet erzeugt die folgende Ausgabe
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)
Der Quellcode für diesen Artikel ist hier. Die Support-Klasse SingletonV3 ist hier
Das Ergebnis der Implementierung hat mich als Konsumenten des Codes zunächst zufrieden gestellt. Ich konnte typisierte Eigenschaften abrufen und festlegen. Als Betreuer des Codes musste ich jedoch die Codedatenstrukturen und Codeschleifen jedes Mal manuell aktualisieren, wenn ich neue Abschnitte und neue Eigenschaften hinzufügte. Darüber hinaus habe ich dadurch nur einen Mechanismus/ein Muster erhalten, das ich immer dann verwenden kann, wenn ich in verschiedenen Anwendungen neue Konfigurationseigenschaften benötige.
Siehe meinen nächsten Beitrag, der eine alternative Implementierung dokumentiert, um die von mir aufgeführten Nachteile zu beheben und gleichzeitig die Vorteile beizubehalten.
Das obige ist der detaillierte Inhalt vonAuf dem Weg zu mühelosen Python-Konfigurationsdateien Version 1. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!