Hallo zusammen,
ich bastel aktuell an einem Python Package um diverse Messgeräte zu
steuern. Solange das ganze nur für mich war, habe ich einfach so etwas
wie die IP Adresse der Ethernet zu GPIB Bridge als default Parameter im
Konstruktor gesetzte. Aber nun benutzen auch andere das Package in
leicht anderen Setups.
Daher die Frage: Wie speichert man am elegantesten Konfigurationsdaten,
so dass das Package sie von überall aus finden kann.
Sehr oft teste ich nur mal eben schnell etwas in der Konsole und da
würde ich es gerne vermeiden jedes Mal IP Adressen usw. eintippen zu
müssen.
Ich hätte es gerne z.B. so:
import package
instrument = package.HP34401A(gpib=4)
instrument.get_reading()
Die IP Adresse des Ethernetadapters soll irgendwo gespeichert sein, wo
das package ran kommt. Ändern würde ich sie dann gerne über Methoden des
Packages
z.B.
package.set_bridge_ip("192.168.0.7")
Gibt es hierfür einen konventionellen Weg? Sicher gibt es unter Windows
und Linux irgendwelche Ordner die immer da sind und in die man eine
config Datei legen könnte, aber vielleicht weiß ja jemand, wie man es
"richtig" macht.
Vielen Dank und viele Grüße
Philipp
Phil schrieb:> Gibt es hierfür einen konventionellen Weg? Sicher gibt es unter Windows> und Linux irgendwelche Ordner die immer da sind und in die man eine> config Datei legen könnte, aber vielleicht weiß ja jemand, wie man es> "richtig" macht.
Alle Wege führen nach Rom, von daher keine Ahnung, ob dieser Weg der
richtige ist. Aber ich
würde der Klasse HP34401A eine classmethode spendieren, welche die
Klasse aus einer Konfiguration initialisiert. OB die Konfiguration dann
in toml, yaml, json oder was anders ist spielt keine Rolle.
Dann kann dein Programm die üblichen verdächtigen (Ordner) abklappern
und wenn dort eine Konfiguration liegt wird die Klasse damit erzeugt.
ungefähr so:
Imonbln schrieb:> würde der Klasse HP34401A eine classmethode spendieren, welche die> Klasse aus einer Konfiguration initialisiert. OB die Konfiguration dann> in toml, yaml, json oder was anders ist spielt keine Rolle.> [...]> ungefähr so:>>
Das wäre ein Ansatz, würde allerdings erfordern, daß Du für jede
mögliche Methode zur Konfiguration eine eigene Klassenmethode schreiben
mußt, was -- je nachdem, was Du alles anbieten möchtest, einerseits
einen recht hohen Aufwand mit viel Boilerplate bedeuten kann und
andererseits provoziert, daß wohlmeinende Anwender "freundlich anregen",
Du mögest doch bitte außerdem noch ihre tolle und völlig unverzichtbare
Möglichkeit anbieten. ;-)
Möglicherweise könnte es daher einfacher sein, wenn der Konstruktor
einfach ein Dictionary (dict()) mit den Konfigurationsdaten übernimmt,
dieses auf Fehler und Vollständigkeit überprüft und diese Daten benutzt.
Dann spielt es keine Rolle mehr, woher die Daten kommen: aus einem
csv.DictReader, einer .ini-Datei die mit configparser gelesen und
umgewandelt wurde, aus einem DictCursor einer Datenbank, einer toml /
yaml / json-Datei, oder womöglich aus einer der einfachsten aller
Konfigurationsdateiformate in Python, nämlich: Python-Code. ;-)
Lustigerweise bietet Python für solche Dinge eine weitere hübsche
Möglichkeit, nämlich die **kwargs, also beliebige Keyword-Argumente
übergeben zu können:
Der geneigte Leser möge beachten, wie ich im Initializer der Klasse für
Parameter, die Methode "pop()" und für optionale Parameter die Methode
"get()" benutze, siehe Kommentar "yay". Außerdem muß das
Konfigurationsdictionary zum Aufruf der Klasse mit '**' übergeben
werden, siehe Kommentar "Syntax!".
Sheeva P. schrieb:> Der geneigte Leser möge beachten, wie ich im Initializer der Klasse für> Parameter, die Methode "pop()" und für optionale Parameter die Methode
Dein Vorschlag hat aber den Nachteil, dass er die Information welche
Parameter die Klasse braucht hinter den Ominösen **kwargs, versteckt.
Schön das eine Klasse dann ein Key-Error beim Erzeugen wirft, wenn Sie
nicht alle Parameter bekommt, welche sie gerne hätte, durch den pop
Einsatz. Aber sauberes Design (was du meisten mit Leidenschaft
vertrittst) sieht in diesen Fall anders aus.
Sicher es gibt fälle in welchen **kwargs eine gute Option ist
(Datenbanken, Protokoll Header, etc) aber dieser ist keiner davon und
der Nachteil das man nur durch Codelesen (oder Dokumentation, wenn
Vorhanden) herausbekommt was der Konstruktor wirklich will widerspricht
auch den Zen of Python in mindestens folgenden Punkten:
* Beautiful is better than ugly.
* Explicit is better than implicit.
* Readability counts.
Abgesehen davon kannst du die Klasse auch ganz klassisch so schrieben
Deine Tricks gehen dennoch: