Lesen und Schreiben von Klassen in CSV

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.
zegru
User
Beiträge: 49
Registriert: Freitag 9. Oktober 2020, 09:22

Noch eine Frage, in diesem Zusammenhang, wo ebenfalls alles Recherchieren und Probieren nichts geholfen hat: Ich möchte die Objekte nicht nur schreiben, sondern auch lesen, und sie kommen dann in eine Datenbank, und verwenden hierfür SQLAlchemy. Habt ihr einen weiteren Tipp für mich?
__deets__
User
Beiträge: 14533
Registriert: Mittwoch 14. Oktober 2015, 14:29

Das geht nur, indem du zusätzlich den Typnamen speicherst, und eine Factory für die Objekte baust. Sowas kann man zb mit Metaklassen machen.
Benutzeravatar
__blackjack__
User
Beiträge: 13100
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Hm, bei SQLAlchemy hat man dann doch schon die ORM-Klassen, beziehungsweise kann man sich ja Mapper auf vorhandene Klassen erstellen.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
zegru
User
Beiträge: 49
Registriert: Freitag 9. Oktober 2020, 09:22

Hm, ich sehe schon: Ich muss mich noch tiefgehender mit Python beschäftigen, Kenntnisse anderer Programmiersprachen erweitert um Comprehensions reicht nicht aus. Die Python-Welt ist doch größer als vermutet. Vor allem das Konzept der Metaklassen ist mir ziemlich neu. Gibt es da eine Einführung, die nicht bei 0 anfängt? Also die nicht unbedingt damit anfängt, wie man den Rechner einschaltet und Python installiert? Und auch keine, die bei 150 anfängt ("Was unterscheidet dieses obskure Modul von jenem?").

Ich habe einstweilen mal probiert, attrib und SQLAlchemy zu verheiraten. Leider kein Erfolg bis jetzt.
Geht, aber halt ohne attr:

Code: Alles auswählen

class Test(Base):
    __tablename__ = "test"
    a = Column(Integer, primary_key=True)
    b = Column(Integer)
Der naive Ansatz mit attr geht nicht, weil angeblich kein Primärschlüssel definiert ist:

Code: Alles auswählen

@attrs(frozen=True)
class Test(Base):
    __tablename__ = "test"
    a = attrib(Column(Integer, primary_key=True))
    b = attrib(Column(Integer))
__deets__
User
Beiträge: 14533
Registriert: Mittwoch 14. Oktober 2015, 14:29

Das man mit SQLAlchemy CSV lesen/schreiben kann, halte ich für unwahrscheinlich. Und eine Kombination mit attrs ist nicht sinnvoll, SA selbst ist ja hoch declarative, und baut sich eigene Klasse - das kommt sich alles in die Quere. - ok, snafu hat gezeigt, dass es geht. Ich finde es immer noch etwas komisch, aber gut.

Statt Metaklassen sind vielleicht auch eher Klassendekoratoren (wie attrs selbst sie benutzt) eine gute Wahl. Damit kannst du zb die erzeugte Methode zum iterieren der Attribute so ummanteln, dass sie vorher noch den Klassennamen ausgibt. Und gleichzeitig eine globale Registry für die genannte Factory füttert, du musst ja eine Zuordnung von Klassenname auf Klasse hinbekommen, und die restlichen Werte dann Typwandeln und einlesen basierend auf der Attribut-Deklaration.

Das ist aber auch alles ganz schön viel Maschinerie. Über wieviele Klasse reden wir denn hier? Denn man kann das bei einigen wenigen ja auch einfach erstmal “zu Fuß” programmieren. Die ganze Meta-Magie ist fein, aber auch oft etwas undurchdringbar.
Benutzeravatar
snafu
User
Beiträge: 6740
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

__deets__ hat geschrieben: Freitag 19. November 2021, 13:46 Wenn man will, kann man ja aber auch https://docs.python.org/3/library/dataclasses.html benutzen. Das ist vielleicht nicht ganz so umfangreich, aber vieles kann es eben auch schon.
Ich finde sogar, dass sich dataclasses besser in die Sprache einfügt als dieses attrs-Modul. Da brauche ich nur den @dataclass-Dekorator an die Klasse kleben und habe direkt die benötigte Magie.

Und mit SQLAlchemy geht es wohl so: https://docs.sqlalchemy.org/en/14/orm/m ... tive-table
__deets__
User
Beiträge: 14533
Registriert: Mittwoch 14. Oktober 2015, 14:29

Für attrs geht das wohl so: https://docs.sqlalchemy.org/en/14/orm/m ... tive-table - aber das backend ist doch immer noch nicht CSV, was bringt das einem?
Benutzeravatar
snafu
User
Beiträge: 6740
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Und hier hat jemand ein Modul gebastelt, das dataclasses mit CSV-Daten befüllen kann: https://pypi.org/project/dataclass-csv/
zegru
User
Beiträge: 49
Registriert: Freitag 9. Oktober 2020, 09:22

__deets__ hat geschrieben: Sonntag 21. November 2021, 12:32 Das ist aber auch alles ganz schön viel Maschinerie. Über wieviele Klasse reden wir denn hier? Denn man kann das bei einigen wenigen ja auch einfach erstmal “zu Fuß” programmieren. Die ganze Meta-Magie ist fein, aber auch oft etwas undurchdringbar.
Eben. Ich dachte, das wäre eventuell ganz einfach, sowas wie "importier einfach dieses Modul hier". Es scheint sich aber, wenn es mal funktionieren sollte, um einen ziemlichen Aufriss zu handeln. Es handelt sich auch bei mir um eine einzige Klasse, deshalb ist es das einfachste, wenn ich das mit weniger Library-Unterstützung mache, sonst schieße ich mit Kanonen auf Spatzen und fahre 10x soviel Boilerplate Code ein, um etwas zu sparen. Sparen um jeden Preis!
Aber als Sekundäreffekt gab es viele wertvolle Einsichten in Python. Danke!
__deets__
User
Beiträge: 14533
Registriert: Mittwoch 14. Oktober 2015, 14:29

Na für eine Klasse ginge das Modul von snafu, dataclasses_csv.
Benutzeravatar
snafu
User
Beiträge: 6740
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

@zegru
Also eine Bibliothek empfiehlt sich dafür schon, damit man eben nicht alles zu Fuß machen muss. Dein Problem ist eher, dass du noch keinen einfachen Ansatz für dein Vorhaben gefunden hast. Wie gesagt, schau dir mal das dataclass-csv Modul näher an.

Hier etwas Beispiel-Code aus der Doku:

Code: Alles auswählen

@dataclass
class User:
    firstname: str
    email: str
    age: int

with open(filename) as users_csv:
    reader = DataclassReader(users_csv, User)
    for row in reader:
        print(row)
Also eigentlich relativ simpel und die Typ-Umwandlungen gibt's gratis dazu. Oder entspricht das nicht dem, was du dir vorgestellt hast?
zegru
User
Beiträge: 49
Registriert: Freitag 9. Oktober 2020, 09:22

Leider kann ich ja dataclass nicht verwenden, da ich ja auch SQLAlchemy für meine Klasse hernehme. Ich verwende jetzt halt das Modul csv und habe eine zusätzliche Methode in der Klasse Test geschrieben, die mir die einzelnen Felder als Tupel zurück liefert. Ich iteriere dann über eine Liste von Test Objekten und rufe dort mit csv.writerow() das Ergebnis des Tupellieferanten des Objekts zurück. Lediglich Felder->Tupel mache ich also manuell.
__deets__
User
Beiträge: 14533
Registriert: Mittwoch 14. Oktober 2015, 14:29

Ahhhh. Das ist mir entgangen, dass es auch um SA Objekte geht. Aber dafür hat Snafu doch eine Integration von, \ SA & dataclasses gezeigt. Ob das dann in der Summe immer noch mit dataclasses_csv arbeitet, musst du ausprobieren.
Benutzeravatar
snafu
User
Beiträge: 6740
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Okay, wenn die dataclass wirklich nur Mittel zum Zweck ist und eigentlich nicht benötigt wird, dann würde ich den Gedanken wieder verwerfen. Ein Modul für die Umwandlung von SQLAlchemy-Klassen in CSV kenne ich nicht und habe auf die Schnelle auch nichts dazu gefunden. Da bleibt dir wohl nur der händische Weg, den du ja offenbar auch schon gehst.
Antworten