FileDB

Stellt hier eure Projekte vor.
Internetseiten, Skripte, und alles andere bzgl. Python.
Benutzeravatar
lynadge
User
Beiträge: 112
Registriert: Sonntag 4. April 2010, 10:17

Hallo Leute,

ich wollte heute meine kleine Lib, FileDB vorstellen. Ist nix großes, ich habe sie für meinen kleinen Blog erstellt und um überhaupt einmal ein kleines Projekt auf Github liegen zu haben. Vom Prinzip her wird auch nur via "pickle" ein dictionary in eine Binärdatei abgelegt und wieder geholt. dazu habe ich noch ein paar Methoden zum besseren handhaben erstellt.

Vielleicht gefällt es euch ja und der ein oder andere kann was mit anfangen. Vorrangig stell ich aber das Projekt hier vor um mir Tipps zu hohlen ob ich alles halbwegs korrekt gemacht habe und was man noch verbessern könnte.

Viel Spaß damit!

https://github.com/deadshox/FileDB

Code: Alles auswählen

# -*- coding: utf-8 -*-
"""
FileDB
------

FileDB is a small handler to use files as database.

Copyright (c) 2011 Daniel Brüggemann.
License: WTFPL2, see LICENSE.txt for details.
"""

__author__ = 'Daniel Brüggemann'
__version__ = '0.5'
__license__ = 'WTFPL2'

import os
import pickle
import zipfile
import time
import logging
import operator
import errno
import hashlib

class FileDB:
    # -------------------------------------------------------------------------
    def __init__(self, db, filebase='filebase', logname='filedb.log'):
        self._filebase = filebase
        self._path = os.path.join('.', filebase + os.sep)
        self._bin = os.path.join(self._path, '{0}.bin'.format(db))
        self.data = {}
        self.checksum = ''
        self.new_checksum = ''

        # set logger
        logging.basicConfig(filename=logname)

        # create 'base' if not exist
        try:
            os.mkdir(self._path)
        except OSError as e:
            if e.errno == errno.EACCES:
                logging.error('Permission denied to create Folder: "{0}".'\
                              .format(self._path))
                raise
            elif e.errno == errno.EEXIST:
                logging.warning('Folder: "{0}" already exist.'\
                                .format(self._path))
        else:
            logging.warning('Create init path: "{0}".'.format(self._path))

            self._bin = os.path.join(self._path, '{0}.bin'.format(db))

        self.load()


    # -------------------------------------------------------------------------
    def load(self):
        """Load data from file."""

        try:
            with open(self._bin, 'rb') as handle:
                self.data = pickle.load(handle)
        except IOError as e:
            if e.errno == errno.ENOENT:
                try:
                    open(self._bin, 'w').close()
                except IOError:
                    logging.error('Can\'t create new file in load(): "{0}".'\
                                  .format(self._bin))
                else:
                    self.checksum = self.get_checksum()
                    logging.warning('Create file: "{0}", given was not found.'\
                                    .format(self._bin))
            elif e.errno == errno.EACCES:
                logging.error('Permission denied to given file: "{0}".'\
                              .format(self._bin))
        except EOFError:
            logging.warning('EOFError in given file: "{0}".'.format(self._bin))
        else:
            self.checksum = self.get_checksum()

    # -------------------------------------------------------------------------
    def reload(self):
        """Reload the data if checksum has changed."""

        self.new_checksum = self.get_checksum()

        if not self.checksum == self.new_checksum:
            try:
                with open(self._bin, 'rb') as handle:
                    self.data = pickle.load(handle)
            except IOError:
                logging.error('Can\'t open the given file in reload(): "{0}".'\
                              .format(self._bin))

    # -------------------------------------------------------------------------
    def save(self):
        """Save data to file."""

        try:
            with open(self._bin, 'wb') as handle:
                pickle.dump(self.data, handle)
        except IOError:
            logging.error('Error while save file: "{0}" not found!'\
                          .format(self._bin))
            raise

    # -------------------------------------------------------------------------
    def sort_by(self, sort='id'):
        """Sort data by key."""

        l = []
        for i in self.data:
            l.append(self.data[i][sort])

        l.sort()
        l.reverse()

        return l

    # -------------------------------------------------------------------------
    def get_checksum(self):
        """Get sha1 checksum of a given file."""

        stat = os.stat(self._bin)

        h = hashlib.sha1()
        h.update('{0}{1}'.format(stat.st_size, stat.st_mtime))

        return h.hexdigest()

    # -------------------------------------------------------------------------
    def create_id(self, data):
        """Creates an id as a hex digget from a integer."""

        try:
            return hex(int(data))[2:]
        except (TypeError, ValueError):
            logging.error('Given data must be a integer: "{0}".'.format(data))

    # -------------------------------------------------------------------------
    def del_db(self):
        """Delete the db."""

        try:
            os.remove(self._bin)
        except OSError:
            logging.error('Could not remove db: "{0}".'.format(self._bin))

    # -------------------------------------------------------------------------
    def del_base(self):
        """Delete the db base."""

        try:
            os.rmdir(self._path)
        except OSError:
            logging.error('Directory: "{0}" is not empty, please clear it.'\
                          .format(self._path))

    # -------------------------------------------------------------------------
    def backup(self, backup_path=''):
        """Backup the filebase or only a file."""

        try:
            os.mkdir(backup_path)
        except OSError:
            pass
        else:
            logging.warning('Backup path: "{0}" created.'.format(backup_path))

        filename = time.strftime('%Y%m%d%H%M', time.localtime(time.time()))
        f = os.path.join(backup_path, '{0}.zip'.format(filename))

        with zipfile.ZipFile(f, 'w') as backup:
            backup.write(self._filebase)
            for bkp_file in os.listdir(self._path):
                backup.write(os.path.join(self._filebase, bkp_file),
                             compress_type=zipfile.ZIP_DEFLATED)
Gruß, deadshox

UPDATE: Version 0.2 - 18.07.2011
UPDATE: Version 0.3 - 18.07.2011
UPDATE: Version 0.4 - 26.07.2011
UPDATE: Version 0.5 - 28.07.2011
Zuletzt geändert von lynadge am Donnerstag 28. Juli 2011, 11:59, insgesamt 4-mal geändert.
Benutzeravatar
snafu
User
Beiträge: 6740
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Zum Zusammensetzen von Pfaden eignet sich `os.path.join()` besser als das, was du da mit `os.sep` betreibst.

Funktionen/Methoden sollten, sofern sie nicht zum reinen Überprüfen gedacht sind, nicht `True` oder `False` zurückgeben. Für diesen Anwendungsfall wurden Exceptions erfunden, von denen man auch ruhig Gebrauch machen sollte. Im Fehlerfall wird die Ausnahme geworfen, ansonsten wird einfach nichts zurückgegeben (außer natürlich man hat irgendwelche Werte, die man ausgeben will oder sowas). Damit erspart sich der Anwender unnötiges C-artiges Überprüfen des Rückgabewerts, was sowohl bei der Implementierung als auch bei der Anwendung für weniger Code sorgt.

Und noch was: Ein "blankes" `except` ist nicht gut, da es die Fehlersuche beim Programmieren erschwert, wenn z.B. ein `NameError` geworfen wird. Lieber die konkrete Ausnahme(n) hinschreiben, die man behandeln möchte. Was du das machst, ist jeglichen Fehler in eine allgemeine Fehlermeldung zu "übersetzen", was die eigentlich Ursache verschleiert. Es ist in Python durchaus üblich, dass die verwendeten Funktionen ggf ihre eigenen Exceptions ohne große Nachbehandlung werfen.
Benutzeravatar
lynadge
User
Beiträge: 112
Registriert: Sonntag 4. April 2010, 10:17

Danke. :)

Das sind noch doofe Angewohnheiten, ich werde es nachbessern.
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

Code: Alles auswählen

# sort the data from file -------------------------------------------------
    def sort_by(self, sort='id'):
        list = []
        for i in self._data:
            list.append(self._data[i][sort])

        list.sort()
        list.reverse()

        return list
kann man zu (ungetestet)

Code: Alles auswählen

import operator
def sort_by(self, sort='id'):
    return sorted(self._data.values(), key=operator.itemgetter(sort), reverse=True)
Umschreiben und spart sich das manuelle rumkopieren. Daneben wird mir das umdrehen nicht ganz klar.

Statt deiner "Schlagzeilen"-Kommentare über den Funktionen solltest du lieber Docstrings benutzen.

Was du da in `check` treibst ist reichlich gefaehrlich, wenn denn jetzt jemand wirklich eine Datei namens "somefile.bin" löschst du sie.[1]

Bei den blanken `excepts`, die Snafu schon erwähnt hat, solltest du zumindest noch die Exceptions selbst abfangen und ihre Fehlermeldung mitloggen. Das gilt auch wenn du das in `except Exception:` änderst. Auch hier ist `except Exception as e:` besser (mit der Ausgabe natürlich).

[1] Das zieht auch ein paar rechtliche Probleme nach sich, da du nirgends bekannt gibst das du das machst, kann man evtl von Arglist sprechen und dich so haftbar machen -- was ansonsten bei "Schenkungen" nicht geht. Ich bin kein Jurist, aber hier solltest du vorsichtig sein.
deets

Wozu ist das Modul denn eigentlich gut? Also, warum nicht mit Python Bordmitteln wie pickle, shelve, sqlite und berkley-db arbeiten?
Benutzeravatar
microkernel
User
Beiträge: 271
Registriert: Mittwoch 10. Juni 2009, 17:27
Wohnort: Frankfurt
Kontaktdaten:

Hallo,

um Pfade mit einander zu verbinden, wie in Zeile 31:

Code: Alles auswählen

self._path = '.' + os.sep + self._filebase + os.sep
Würde ich lieber:

Code: Alles auswählen

self._path = os.path.join('.', self._filebase)
verwenden.

Lg
microkernel
Benutzeravatar
microkernel
User
Beiträge: 271
Registriert: Mittwoch 10. Juni 2009, 17:27
Wohnort: Frankfurt
Kontaktdaten:

Ach verdammt! Ich sollte lieber erstmal die Antworten (z.B.: von @snafu) lesen... :roll:
Benutzeravatar
lynadge
User
Beiträge: 112
Registriert: Sonntag 4. April 2010, 10:17

Welchen Vorteil bringt 'os.path.join' gegenüber 'os.sep'?

@snafu, wurde alles in die TODO übernommen. :)

@cofi, die Sortier-Methode habe ich deshalb so geschrieben da ich aus irgendwelchen gründen nicht mit 'sorted' zufrieden war. Ich werde es noch mal mit in die TODO auf nehmen und testen. ;)

Das mit der Check-Methode, da hast du recht, das werde ich überarbeiten. Habe ich gar nicht bedacht das jemand seine Datei 'somefile.bin' nennen könnte, dachte der Name ist schon recht unnormal. Aber ich sehe noch etwas was ich ändern sollte. Das einzig gute, die Methode wird erst bei bedarf genutzt, nicht Automatisch. :P Aber danke für den Hinweis.

@deets, das Modul ist eine Art Wrapper mit Zusatzfunktionen für Pickle. Z.b. hat Pickle keine Backupfunktion. Der Grund warum ich keine vorgefertigte Lösung oder Datenbank verwende ist der, das ich an dem Projekt lernen möchte.

Gruß, deadshox
Benutzeravatar
snafu
User
Beiträge: 6740
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

deadshox hat geschrieben:Welchen Vorteil bringt 'os.path.join' gegenüber 'os.sep'?
Das Zusammensetzen von Pfaden ist damit IMHO schöner (wie bereits erwähnt). In deinem Fall würde ich es aber ganz weglassen, denn dein erzeugtes `./filebase/` ist hier so ziemlich das selbe wie `filebase` - eine relative Pfadangabe eben. Das spätere `glob('./filebase/*')` entspricht einem `os.listdir('filebase')`. Soll heißen: Du machst die Dinge hier eigentlich komplizierter als nötig. ;)
Benutzeravatar
lynadge
User
Beiträge: 112
Registriert: Sonntag 4. April 2010, 10:17

Hab jetzt mal das Update gemacht, was auch eure Verbesserungsvorschläge mit einbezieht. ;)
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Hallo.

Einiges wurde glaube ich schon genannt:

- Die """...""" sind keine Kommentare. Kommentage werden mit einem `#` eingeleitet
- Die ganzen "-------------------------------" sind vollkommen unnötig
- Suche mal nach Docstrings
- `file` is ein built-in, du solltest daher daran keine eigenen Objekte binden
- Dateien solltest du mit dem with-Statement öffnen
- Benutze keine leeren except-Anweisungen, gib immer an, welche Fehler bearbeitet werden
- Setze Strings nicht mit `+` zusammen, sondern benutze String Formatting
- Du brauchst nicht zu zu prüfen, ob es sich um eine Datei handelt, versuche sie einfach zu öffnen und warte ggf. die Fehlermeldung ab
- Wenn du get- und set-Methoden hast, welche nicht mehr machen als einen übergebenen Wert zu setzten, oder den gesetzten als Ergebnis zu liefern, dann kannst du dir die Methoden auch sparen.
- `list` ist wieder ein built-in-Name und sollte nicht überschrieben werden
- `file` ist auch ein schlechter Name, wenn es sich bei dem Inhalt und einen Pfad handelt
Das Leben ist wie ein Tennisball.
Benutzeravatar
lynadge
User
Beiträge: 112
Registriert: Sonntag 4. April 2010, 10:17

EyDu hat geschrieben: - Die """...""" sind keine Kommentare. Kommentage werden mit einem `#` eingeleitet
- Suche mal nach Docstrings
- `file` is ein built-in, du solltest daher daran keine eigenen Objekte binden
- Dateien solltest du mit dem with-Statement öffnen
- Setze Strings nicht mit `+` zusammen, sondern benutze String Formatting
- `list` ist wieder ein built-in-Name und sollte nicht überschrieben werden
- `file` ist auch ein schlechter Name, wenn es sich bei dem Inhalt und einen Pfad handelt
Danke, habs geändert. :) Hatte das mit den docstrings erst falsch verstanden.
EyDu hat geschrieben: - Die ganzen "-------------------------------" sind vollkommen unnötig
Finde sie machen den Quellcode aber ein wenig übersichtlicher. ;)
EyDu hat geschrieben: - Benutze keine leeren except-Anweisungen, gib immer an, welche Fehler bearbeitet werden
Ich logge doch bei jeder Exception einen Fehler mit oder habe ich das etwa falsch verstanden?
EyDu hat geschrieben: - Du brauchst nicht zu zu prüfen, ob es sich um eine Datei handelt, versuche sie einfach zu öffnen und warte ggf. die Fehlermeldung ab
Wo meinst du das genau?
EyDu hat geschrieben: - Wenn du get- und set-Methoden hast, welche nicht mehr machen als einen übergebenen Wert zu setzten, oder den gesetzten als Ergebnis zu liefern, dann kannst du dir die Methoden auch sparen.
Könnte aber vielleicht für die Zukunft nützlich sein. Denke ich.
deets

deadshox hat geschrieben: Könnte aber vielleicht für die Zukunft nützlich sein. Denke ich.
Wenn es das werden sollte, dann kannst du immer noch ein property draus machen. Python ist nicht Java. Getter & Setter sind unnoetiger Boilerplate-Code. Und programmieren auf eine schoene Zukunft hin klappt selten bis nie.
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Hallo.
deadshox hat geschrieben:
EyDu hat geschrieben: - Die ganzen "-------------------------------" sind vollkommen unnötig
Finde sie machen den Quellcode aber ein wenig übersichtlicher. ;)
Dann benutze doch einfach ein oder zwei Leerzeilen mehr ;-)

deadshox hat geschrieben:
EyDu hat geschrieben: - Benutze keine leeren except-Anweisungen, gib immer an, welche Fehler bearbeitet werden
Ich logge doch bei jeder Exception einen Fehler mit oder habe ich das etwa falsch verstanden?
Wenn du eine `except` hast, welches ohne eine Einschränkung der Fehlermeldung arbeitet, dann verschluckst du wirklich alle Fehler. Damit hast du gleich mehrere Probleme. Dadurch, dass du alle Fehler abfängst, ist nicht sofort ersichtlich wo der Fehler auftritt. Unter Umständen bekommst du das Problem erst in einer anderen Methode mit, welche das Fehlersuchen im Prinzip unmöglich macht. Zum anderen fängst du damit wirklich alle Fehler ab, auch jene, die du nicht behandeln kannst oder mit denen du nicht einmal gerechnet hast. Mal ein simples Beispiel:

Code: Alles auswählen

        try:
            with open(self._bin, 'rb') as handle
                int("spam")
                self._data = pickle.load(handle)
        except:
            logging.warning('No data obtained.')
Dann hast du zwar geloggt, dass etwas nicht funktioniet hat, du hast aber im Prinzip keine Ahnung wo es passiert ist. Fehler, welche du nicht behandeln kannst, solltest du daher auch gar nicht erst behandeln. Das macht eine Fehlersuche im Prinzip unmöglich und produziert im schlimmsten Fall einen inkonsistenten Zustand, der noch viel größere Probleme aufwirft.
deadshox hat geschrieben:
EyDu hat geschrieben:- Du brauchst nicht zu zu prüfen, ob es sich um eine Datei handelt, versuche sie einfach zu öffnen und warte ggf. die Fehlermeldung ab
Wo meinst du das genau?
In deiner `_load`-Methode. Versuche die Datei zunächst lesend zu öffnen (die "Standard Fall" sollte möglichst als erstes kommen) und wenn das nicht funktioniert versuche das Problem zu behandeln. Du solltest hier auch bedenken, dass `self._bin` zum Zeitpunkt des `isfile`-Test noch existiert, beim lesenden öffnen aber bereits nicht mehr. So etwas passiert ständig ;-)
deadshox hat geschrieben:
EyDu hat geschrieben: - Wenn du get- und set-Methoden hast, welche nicht mehr machen als einen übergebenen Wert zu setzten, oder den gesetzten als Ergebnis zu liefern, dann kannst du dir die Methoden auch sparen.
Könnte aber vielleicht für die Zukunft nützlich sein. Denke ich.
Dafür gibt es in Python `properties` um diesen Fall sauber und transparent zu handhaben. Wirf dazu mal die Suchmaschine deiner Wahl an.

Sebastian
Das Leben ist wie ein Tennisball.
Benutzeravatar
lynadge
User
Beiträge: 112
Registriert: Sonntag 4. April 2010, 10:17

Danke euch beiden, die getter und setter Methoden habe ich wieder entfernt und die Eigenschaft 'data' auf global gesetzt.
EyDu hat geschrieben: Dann benutze doch einfach ein oder zwei Leerzeilen mehr ;-)
Hm, das ist dann wohl Geschmackssache. Ich bevorzuge meine Methode, da sie es auch einfacher macht, die 79zeichen einzuhalten und sie lockert alles ein wenig auf. :)
EyDu hat geschrieben: Wenn du eine `except` hast, welches ohne eine Einschränkung der Fehlermeldung arbeitet, dann verschluckst du wirklich alle Fehler. Damit hast du gleich mehrere Probleme. Dadurch, dass du alle Fehler abfängst, ist nicht sofort ersichtlich wo der Fehler auftritt. Unter Umständen bekommst du das Problem erst in einer anderen Methode mit, welche das Fehlersuchen im Prinzip unmöglich macht. Zum anderen fängst du damit wirklich alle Fehler ab, auch jene, die du nicht behandeln kannst oder mit denen du nicht einmal gerechnet hast. Mal ein simples Beispiel:

Code: Alles auswählen

        try:
            with open(self._bin, 'rb') as handle
                int("spam")
                self._data = pickle.load(handle)
        except:
            logging.warning('No data obtained.')
Dann hast du zwar geloggt, dass etwas nicht funktioniet hat, du hast aber im Prinzip keine Ahnung wo es passiert ist. Fehler, welche du nicht behandeln kannst, solltest du daher auch gar nicht erst behandeln. Das macht eine Fehlersuche im Prinzip unmöglich und produziert im schlimmsten Fall einen inkonsistenten Zustand, der noch viel größere Probleme aufwirft.
/quote]
Also dann eher so etwas wie:

Code: Alles auswählen

try:
    with open(self._bin, 'rb') as handle
        int("spam")
        self._data = pickle.load(handle)
except Exeption, e:
    logging.error('Error: ' % e)
Wenn nicht, kannst du etwas genauer werden? Wenn es oberes nicht ist, kann ich mir ja das try:except gleich sparen.
EyDu hat geschrieben: In deiner `_load`-Methode. Versuche die Datei zunächst lesend zu öffnen (die "Standard Fall" sollte möglichst als erstes kommen) und wenn das nicht funktioniert versuche das Problem zu behandeln. Du solltest hier auch bedenken, dass `self._bin` zum Zeitpunkt des `isfile`-Test noch existiert, beim lesenden öffnen aber bereits nicht mehr. So etwas passiert ständig ;-)
Ach, jetzt versteh ich. :)
BlackJack

@deadshox: Wenn Du hinter den Logging-Aufruf nicht noch ein ``raise`` setzt, dann kannst Du Dir das ``except`` vielleicht wirklich sparen. Die Frage ist doch an jeder Stelle, ob Du die Ausnahme überhaupt ”verschlucken” solltest. In dem Beispiel hat irgendetwas beim Laden/Parsen der Datei nicht funtkioniert. Das Programm würde aber weitermachen, als wäre nichts passiert. Sollte es das tun? Denn danach wird ja sicher mit den Daten irgendetwas gemacht. Also mit den Daten die nicht geladen werden konnten — also wird es dort entweder wieder eine Ausnahme geben, oder ein falsches Ergebnis.
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

deadshox hat geschrieben:Also dann eher so etwas wie:

Code: Alles auswählen

try:
    with open(self._bin, 'rb') as handle
        int("spam")
        self._data = pickle.load(handle)
except Exeption, e:
    logging.error('Error: ' % e)
Wenn nicht, kannst du etwas genauer werden? Wenn es oberes nicht ist, kann ich mir ja das try:except gleich sparen.
`Exception` fängt noch immer alle Fehler ab, du muss schon prüfen, welche Fehler genau auftreten können. Dazu hilft ein Blick in die Dokumentation zu `open`. Die mögliche Exception ist `IOError`, also behandelst du genau diese:

Code: Alles auswählen

try:
    with open(self._bin, 'rb') as handle
        int("spam")
        self._data = pickle.load(handle)
except IOError:
    logging.error("Could not open file: %s" % self._bin)
Der `ValueError` läuft dann irgendwo anders auf und du bekommst den Fehler noch mit.
Das Leben ist wie ein Tennisball.
Benutzeravatar
lynadge
User
Beiträge: 112
Registriert: Sonntag 4. April 2010, 10:17

@blackjack, in der _load Methode macht es mMn Sinn, da, wenn die Datei nicht existiert, sie angelegt wird. Da muss ja nichts abgebrochen werden.

@EyDu, wäre Variante 1 nicht einfacher, da man die Fehlermeldung dort einfach nur zum Loggen durch reicht? Denn eine direkte Ausgabe wäre für mich persönlich nicht nötig. Evtl könnte man noch ein 'print' setzen für die Konsole. Jeden möglichen Fehler abfangen würde ich irgendwie als zu aufwendig empfinden.
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Einfacher vielleicht, aber unter umständen auch vollkommen falsch. Angenommen, du möchtest zwei Werte (in diesem etwas seltsamen Szenario) vertauschen. Leider verschreibst du dich ein wenig:

Code: Alles auswählen

>>> a, b = 42, 23
>>> try:
...     a, b = beh, ah
... except:
...     pass
... 
>>> a, b                                                                                                             
(42, 23)
Ganz offensichtlich sind `ah` und `beh` nicht vorhanden, da du alle Fehler behandelst, wird dir dies aber nicht auffallen. Das Programm läuft gemütlilch weiter, obwohl hier ein ganz offensichtlicher Fehler vorhanden ist. Vielleicht irgendwann später im Verlauf des Programms gibt es einen Folgefehler, was eine Fehlersuche unglaublich anstregend machen kann. Da ist es natürlich schön, wenn du den Fehler geloggt hast, dir wird das Problem aber unter Umständen gar nicht erst aufflallen (je nach Umfang des Logs). Du verwirfst damit also nicht nur Fehler von außen, sondern möglicherweise auch Programmierfehler.
Das Leben ist wie ein Tennisball.
Benutzeravatar
lynadge
User
Beiträge: 112
Registriert: Sonntag 4. April 2010, 10:17

Ich hoffe ich verstehe dich nicht falsch aber ein:

Code: Alles auswählen

>>> a, b = 42, 23
>>> try:
...     a, b = beh, ah
... except Exception, e:
...     print e
... 
name 'beh' is not defined
Sagt mir doch an, was falsch gemacht wurde.

Es ist ja im Endeffekt nichts anderes als:

Code: Alles auswählen

>>> a, b = 42, 23
>>> a, b = beh, ah
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'beh' is not defined
Nur das es mehr oder weniger abgefangen wurde.

Vielleicht hätte ich noch dazu schreiben sollen das es mehr mein Ziel ist, ein reibungslosen Programmablauf zu erreichen, als eine eine Programm zu haben was mit Fehlermeldungen um sich wirft, wenn es welche gibt.
Antworten