logging Konfiguration in eigenes Modul auslagern?

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
p90
User
Beiträge: 198
Registriert: Donnerstag 22. Juli 2010, 17:30

Hi,
folgendes Problem:
Ich habe ein Programm bei dem man verschiedene aktivitäten über mehrere Pythonskripte ansprechen kann. z.B. startet das Programm wenn start.py aufgerufen wird, beendet wird es mit stop.py etc.
Nun habe ich zwei Log-Dateien in die bestimmte Daten geloggt werden sollen.
Den Code dafür brauche ich ja nun in allen meinen Skripten.
Ich könnte ihn nun da einfach hineinkopieren aber dann habe ich ihn an N Stellen stehen und wenn was geändert werden muss kann man leicht eine der Dateien übersehen. Deshalb wollte ich diese Konfiguration in ein extra Modul auslagern das ich dann überall importieren kann.
Das sieht momentan so aus:

logginghelper.py

Code: Alles auswählen

try:
	import logging
	import logging.handlers
	import logging.config
	if not logging.__author__ == 'Vinay Sajip <vinay_sajip@red-dove.com>':
		raise AttributeError
except AttributeError, e:
	print >> sys.stderr, 'Apparently wrong logging module installed'
	exit()
except ImportError:
	print >> sys.stderr, 'logging modul not found!'
	exit()

logging.config.fileConfig("config.cfg")

tweetlog = logging.getLogger('tweets')
 
def tweet(tweetobject):
	tweetlog.info(tweetobject.text.replace("\n", ""), extra={'username': tweetobject.user.screen_name, 'id': tweetobject.id})

logging.tweet = tweet

In meinen Programmen mache ich dann nur noch:

Code: Alles auswählen

from logginghelper import logging
und kann ganz normal mit dem logging Modul arbeiten.

Das ganze geht also so weit aber sieht irgendwie sehr unpythonisch aus.
Da ich ja immer versuche meinen Code "richtig" zu schreiben und was zu lernen nun die Frage an euch.
Ist das hier der richtige Weg oder sollte ich das ganze anders machen?
Gibt es da überhaupt einen Weg das anders zu machen?
Schönen Abend euch allen!

p91
Sirius3
User
Beiträge: 17750
Registriert: Sonntag 21. Oktober 2012, 17:20

Hallo p92,

es ist genau der richtige Weg, Funktionen, die in verschiedenen Programmen benutzt werden in Module auszulagern. Ich weiß nicht genau, was Dir an Deiner Lösung unpythonisch vorkommt.

Ein paar Sachen sind mir aufgefallen.
Module sollten nie bei Fehlern das ganze Programm mit exit beenden. Das nimmt dem
Importeur die Möglichkeit mit Alternativen zu reagieren. Stell Dir vor, Du möchtest in
Zukunft zwei verschiedene Logging-Methoden unterstützen, dann wird der Rückfall
auf ein 'Dummy'-Logging durch das exit verhindert.
Ein einfaches

Code: Alles auswählen

raise ImportError('Apparently wrong logging module installed')
kann im Hauptprogramm immer noch in eine "schöne" Fehlermeldung verwandelt werden.
Dadurch wird auch das try um die imports überflüssig.

Über den Author zu prüfen, ob die richtige Version von logging geladen wurde,
halte ich für sehr kritisch. Es widerspricht dem modularen Gedanken von Python
bestimmte Teile durch andere mit der selben Funktionalität ersetzen zu können.
Es ist ein grundlegendes Programmierparadigma, dass es irrelevant ist wie (in Deinem
Fall wer) etwas gemacht wird, sondern nur die Schnittstelle entscheidend ist.
Ein "falsches" logging-Modul bricht spätestens bei logging.config.fileConfig mit
einer Exception ab und kann hier durch einen try-Block in einen sprechenden Fehler
umgewandelt werden:

Code: Alles auswählen

try:
    fileConfig = logging.config.fileConfig
except AttributeError:
    raise AssertionError('Apparently wrong logging module installed')
fileConfig("config.cfg")
Ich stehe prinzipiell Abfragen der Art 'if version<(3,4,0): raise Error'
kritisch gegenüber. Es sollte mir maximal beim Setup als warning gesagt
werden, dass ein installiertes Modul zu alt ist. Dann kann ich die Warnung
auf eigene Gefahr hin ignorieren und vielleicht funktioniert das Programm
für meine Zwecke einwandfrei auch mit einer älteren Version, weil ich die
Funktionen der neueren gar nicht nutze.

Grüße
Sirius
BlackJack

Wann bekommt man denn bei ``import logging`` grundsätzlich einen `ImportError`? Das Modul ist doch Bestandteil der Standardbibliothek‽
p90
User
Beiträge: 198
Registriert: Donnerstag 22. Juli 2010, 17:30

@BlackJack
Da ich momentan nur auf den Author gucke macht das wirklich nicht soo viel Sinn aber
was ich halt schon hatte war, das ein User so schlau war und ein easy-install logging gemacht hat.
Was danach auch immer passiert ist, logging ging dann nicht mehr. Und hatte ja ein ähnliches Problem bei einem easyinstall twitter was eigentlich ein easyinstall python-twitter hätte sein sollen. Nur heißen die imports halt beide twitter.

Ich weiß, du bist der Ansicht das ist Sache des Users aber wenn ich verhindern kann das ich nachts um 3 Anrufe bekomme weil "Es geht nicht und muss doch morgen früh laufen!!!" mache ich das.
BlackJack

@p90: Die Sache mit Benutzer mal aussen vor gelassen verstehe ich immer noch nicht was der ``except ImportError`` beim Import von `logging` bringen soll. Das würde davor ”schützen” wenn der Anwender per Hand die `logging.py` aus der Standardbibliothek löscht. Dann brichst Du das Programm ab. Nur würde das Programm an der Stelle sowieso abbrechen. Ich verstehe den Sinn von dem ``except``-Zweig nicht. Und müsste man dann nicht damit rechnen das der Anwender potentiell *jedes* Modul aus der Standardbibliothek einfach so löscht?

Ich würde bei solchen Anwendern ja eher die Anwendung in ein `virtualenv` stecken — dann kann der Anwender `logging` und `twitter` Module installieren wie er lustig ist.
Antworten