Default-Konfiguration finden
Um einem Python-Skript die nötigen Parameter mitzugeben,
verlasse ich mich gern auf zwei Module.
Mit configparser
kann ich in Python
Konfigurationsdateien einlesen oder schreiben.
Mit argparse
definiere ich eine Kommandozeilenoption,
die angibt,
wo die Konfigurationsdatei liegt.
Oft will ich aber keine Konfigurationsdatei angeben, wenn ich mein Skript starte. Zwar könnte ich ein Shell-Skript oder einen Alias schreiben, welches den Aufruf des Skripts mit den benötigten Parametern versorgt.
Dann wiederum müsste ich dieses Skript oder den Alias ändern, wenn ich einmal eine andere Konfigurationsdatei verwenden will. Besser wäre es, wenn das Skript automatisch an vordefinierten Stellen nach seiner Konfigurationsdatei suchen würde, wenn ich keine vorgebe.
Mit der XDG Base Directory Specification
gibt es eine Konvention,
wo die vordefinierten Stellen
unter anderem für Konfigurationsdateien
liegen sollten.
Und mit xdg_base_dirs
ein Python-Modul,
welches diese Stellen entsprechend der obigen Konvention findet.
Damit kann mein Skript die Konfiguration an diesen Stellen suchen.
Das könnte in etwa so aussehen:
#!/usr/bin/env python3
import argparse
import configparser
import sys
from os.path import ( isfile, join as path_join )
from xdg_base_dirs import ( xdg_config_dirs, xdg_config_home )
def configure(args):
cfn_default ='config.ini'
cf_name = None
if args.config is not None:
cf_name = args.config
else:
if isfile('.{}'.format(cfn_default)):
cf_name = '.{}'.format(cfn_default)
elif isfile(path_join(str(xdg_config_home()), cfn_default)):
cf_name = path_join(str(xdg_config_home()), cfn_default)
else:
for p in xdg_config_dirs():
if isfile(path_join(str(p), cfn_default)):
cf_name = path_join(str(p), cfn_default)
break
if cf_name is not None:
conf = configparser.ConfigParser()
print("Reading config from '{}'".format(cf_name), file=sys.stderr)
conf.read(cf_name)
else:
print('No config file given and none found', file=sys.stderr)
sys.exit(1)
return conf
def parse_args():
"""CLI argument definitions and parsing"""
parser = argparse.ArgumentParser()
parser.add_argument(
'--config', '-c',
help='name of config file',
)
return parser.parse_args()
if '__main__' == __name__:
args = parse_args()
conf = configure(args)
conf.write(sys.stdout)
sys.exit()
Das Beispielskript sucht in der folgenden Reihenfolge nach seiner Konfigurationsdatei:
- Die Datei, deren Name mit der
--config
Option angegeben wurde, ohne weiter zu suchen. - Eine Datei namens .config.ini im aktuellen Verzeichnis (man beachte den vorangestellten Punkt).
- Eine Datei namens config.ini in
$XDG_CONFIG_HOME
. - Die erste gefundene Datei namens config.ini in einem Verzeichnis aus
$XDG_CONFIG_DIRS
.
Wird keine Option --config
verwendet,
nimmt das Skript die erste gefundene Konfigurationsdatei
oder bricht mit Fehlermeldung ab,
wenn es keine finden konnte.