SQLAlchemy Expression Language vs DB-API

Installation und Anwendung von Datenbankschnittstellen wie SQLite, PostgreSQL, MariaDB/MySQL, der DB-API 2.0 und sonstigen Datenbanksystemen.
Antworten
schnitt_tt
User
Beiträge: 10
Registriert: Sonntag 15. Mai 2011, 09:12

Hi,

ich mache gerade meine ersten Schritte mit der Verwendung einer DB unter Python. (Für Python würde ich mich ebefalls als "Grünling" bezeichen, Entwickle jedoch schon länger prozedural und finde das Thema OO und dynamischtypisierte Sprache recht interessant !)

Um mir das arbeiten mit der DB zu erleichtern habe ich bekommen, die Zugriffe via DB-API zu erleichtern (siehe bsp unten). Ich habe ich jedoch die Vermutung das ich eigentlich versuch die SQLAlchemy Expression Language nachzubauen ... wenn dem so ist sollte ich wohl DB-API vergessen und mich mehr mit der SA-EL beschäftigen. ORM ist für mich (noch) kein Thema, das ist mir vorerst noch zu heavy, Pickle möchte ich nicht verwenden, da ich die gesicherten Daten visuell prüfen möchte usw

Beispiel: Zugriffe per Select möchte ich mir durch die Methode: Select() erleichtern:
Um Select-Statement:
SELECT * FROM file_info WHERE typ = 'Directory'
zu erzeugen, wird folgende Methode einer Datenbankklasse aufgerufen:

Code: Alles auswählen

    sql  = 'typ = ?'
    args = ('Directory',)
    it_result = db.select('file_info', sql , args)
Die Methode sieht so aus:

Code: Alles auswählen

    def select (self, tabname,where=None,values=None):
        """ select records from the database.

        @tabname    Tabellenname auf die Zugegriffen werden soll
        @where      Felder die abgefragt werden sollen
        @value      Werte für die Where-Bedingung

        @return     Es wird eine Liste mit den Datenbankeinträgen zurückgegeben (als Dict)

        Beispiel:

        where  = 'master = ? or master = ?'
        values = ('Ami','Abat',)

        Die Methoden macht daraus: master='Ami or master='ABAT'
        """

        if where:
            sql = 'SELECT * FROM {table} WHERE {val}'.format(table=tabname, val=where)
        else:
            sql = 'SELECT * FROM {table} '.format(table=tabname)

        print (sql)
        cursor = self.db.cursor()
        cursor.execute(sql,values)
        records = cursor.fetchall()
        cursor.close()

        # Datenbank-Sätze kommen in eine Liste die pro Satz ein Dict mit der Strutur der DB enthält
        struc   = self.it_struc[tabname]
        it_lis = []
        for row in records:
            combine = zip(struc,row)
            it_lis.append(dict(combine))
            pass

        return it_lis
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Aja.

Will sagen: und weiter?
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
deets

@schnitt_tt

Das sieht doch arg beschraenkt aus. Nur Abfragen auf eine Tabelle, keine Aggregations, Group-By & Order-By Funktionen & Klauseln, zwangsweise Dictionaries als Resultat, immer alle Spalten abgefragt.

Auch keine Komposition von Ausdruecken (als zB eine Suchanfrage erstmal allgemein zu machen, und dann bei Existenz weiteren Filterkriterien nachtraeglich mehr einzuschraenken).

Und eine wirklich gute Abstraktion gibt's auch nicht her, es fehlt ja sowas wie SQL-Dialekte (bestimmte Spaltennamen koennten reserviert sein und muessen in doppelte Anfuehrungszeichen gesetzt werden usw)..

Darum wuerde ich deinen schon selbst gehegten Verdacht bestaetigen - lerne lieber SQLAlchemy.
schnitt_tt
User
Beiträge: 10
Registriert: Sonntag 15. Mai 2011, 09:12

@deets

si, ist ziemlich beschränkt ... das ganze ist eigentlich als Versuch gedacht herauszufinden wie ich mir den Umgang mit einer Datenbank erleichtern kann (Tipparbeit, Übersichtlichkeit etc). Das ganze geprimmel mit "ich bastle mir mein SQL in Strings" geht mir eigentlich ziemlich auf den Keks.
Dachte das mir da SQLAlchemy vielleicht die Arbeit abnehme würde ... aber nach einem ersten Blick auf das Tutorial, müßte ich da ebenfalls zusätzlich Dinge "wrappen"(connect,cursor,close fetch,fetchall kann ich mir ja "sparen" -> bzw "Strings bastel" bleibt erhalten. Bin halt gewonnt "Inline-SQL" zu verwenden (OpenSQL/ABAP) und das ist sehr komfortabel/übersichtlich ...

.. aber damit muß halt in der "anderen" Welt leben ... *grmml

by the way: (OT) aber der Frust muß wohl raus: ..*g
- zusätzlich ständig diese ewigen Modul.Objekt.attribute.methode( objekt.methode() ) Ausdrücke sind für mich halt auch noch gewöhnungsbedürftig und (noch) nicht wirklich übersichtlich
- SQLAlchemy ->ein weiteres Modul das man beachten muß wegen Eigenheiten, neues Release , gibts das noch in 3 Jahren etc ...

-->die OO-Entwickler sind z.T nicht wirklich zu beneiden ....


thx
BlackJack

@schnitt_tt: Viele Punktoperatoren in einer ”Kette” sind nicht die Regel. Ausser die API sieht das so vor, wie es bei SQLAlchemy teilweise der Fall ist. Aber da würde ich nicht verstehen wo das Problem liegt.

Und ob man nun ``obj.spam(arg)`` oder ``spam(obj, arg)`` schreibt, ist wahrscheinlich Gewöhnungssache. Mehr Tipparbeit ist es jedenfalls nicht.
Benutzeravatar
noisefloor
User
Beiträge: 3856
Registriert: Mittwoch 17. Oktober 2007, 21:40
Wohnort: WW
Kontaktdaten:

Hallo,
SQLAlchemy ->ein weiteres Modul das man beachten muß wegen Eigenheiten, neues Release , gibts das noch in 3 Jahren etc ...
Zum einem ist SQLAlchemy bei PyPi als "stable" bezeichnet, d.h. die grundlegende API - und dazu gehört IMHO auch die SQL Expression Language - ändert sich wohl kaum noch.

Wenn das aber ein Grund _gegen_ SQL Alchemy wäre, dann nimm' doch rohes SQL und das für deine Datenbank passende Python DB Modul. Reines SQL hat auch den Vorteil, dass fast keine . drin vorkommen *SCNR*

Gruß, noisefloor
deets

@schnitt_tt

Aber gerade wenn du SA benutzt, bist du an inline-SQL so nah dran wie es geht. Denn du baust Abfragen durch Python-Ausdruecke auf. Die per Definition "inline" sind ;)

Ueber den Lebenszyklus von SA brauchst du dir ebenfalls keine Gedanken machen. Das ist da & zu gut, als das es verschwindet.
schnitt_tt
User
Beiträge: 10
Registriert: Sonntag 15. Mai 2011, 09:12

@BlackJack ...

ich habe mir angewöhnt externe Module immer mit einem prefix zu importieren ... sodas das ich mir im Quelltext bewußt bin was ich aus welchem Modul verwende ...

also

Code: Alles auswählen

import tkinter as tk

dann kommen halt solche Dinge zustande:

Code: Alles auswählen

widget_button1 = tk.ttk.Button(root,......)
oder innerhalb von Klassen: Aufruf Methode einer Instanzvariable:

Code: Alles auswählen

self.gui_abattyp.configure(values=fw.it_abattyps , state='readonly')

aber damit werde ich wohl leben ... ist halt nur ungewohnt.
@Noisefloor/Deets
wegem dem Lebenszyklus komm`ich dann auf euch zurück wenns nicht mehr passt :wink: Nee, mal im ernst, der grundlegende Tenor scheint ja positiv für die Zukunft zu sein .... dh dann ein Punkt mehr es zu verwenden ..

@deets ... "inline" -> :wink:

naja lese mir gerade das ORM-tutorial durch, ist ja nicht zu komplex wie ich anfangs dachte, denke ich mach gleich den Schritt zu ORM. (Naja m:m lass ich mal außen vor). Da brauch ich dann keine mapping mehr Datenbank.structur zu Objekt etc sieht irgendwie komfortabler aus ...

thx

thx ...
Antworten