PEP 8 79 Zeichen

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.
Kalysto
User
Beiträge: 117
Registriert: Freitag 14. April 2017, 15:28

Hallo zusammen,

Ich bin gerade dabei Stück für Stück mein Code PEP 8 gerechter zu machen.
Meine Frage wäre diese 79 Zeichen pro Zeile wie ich das am besten machen würde und ob man das überhaupt anwenden tut?

Mein code bsp. wäre dieser:

Code: Alles auswählen

 self.cur.execute("INSERT INTO `datanorm` (`Barcode`, `user_name`, `sort_number`, `manufacturer`, `manufacturer_designation`, `manufacturer_designation__short`, `manufacturer_number`, `moster_number`, `net_price`, `cutting`, `date_create`) VALUES ('{}', '{}', '{}', '{}', '{}', '{}', '{}', '{}', '{}', '{}', '{}')".format(BARCODE, self.USER, SORT_NUMBER, MANUFACTURER, MANUFACTURER_DESIGNATION, MANUFACTURER_DESIGNATION__SHORT, MANUFACTURER_NUMBER, MOSTER_NUMBER, NET_PRICE, CUTTING, date.today()))
Wie genau würde ich das hier anwenden ?
Sirius3
User
Beiträge: 18274
Registriert: Sonntag 21. Oktober 2012, 17:20

Die 79 Zeichen kann man bei den heutigen breiten Monitoren auch mal auf 100 Zeichen aufweichen, aber 500 ist definitiv zu viel.

Das wichtigste zunächst: man formatiert keine Werte in SQL-Statements hinein, sondern benutzt Platzhalter.
Dann sieht die Tabelle so aus, als ob die noch ein bißchen mehr normalisiert werden sollte.
Es sieht komisch aus, dass alle Werte für die Tabelle anscheinend Konstanten sein sollen.
Cursor sind normalerweise etwas kurzlebiges und sind daher keine Attribute einer Instanz.
Strings und Listen kann man einfach auf mehrere Zeilen aufteilen.

Code: Alles auswählen

cursor.execute("INSERT INTO datanorm (Barcode, user_name, sort_number, "
    "manufacturer, manufacturer_designation, manufacturer_designation__short, "
    "manufacturer_number, moster_number, net_price, cutting, date_create) "
    "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", [
        BARCODE, self.USER, SORT_NUMBER, MANUFACTURER, MANUFACTURER_DESIGNATION,
        MANUFACTURER_DESIGNATION__SHORT, MANUFACTURER_NUMBER, MOSTER_NUMBER,
        NET_PRICE, CUTTING, date.today()])
Benutzeravatar
__blackjack__
User
Beiträge: 14054
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Bei mir würde das so aussehen:

Code: Alles auswählen

        cursor.execute(
            "INSERT INTO datanorm (barcode, user_name, sort_number,"
            "   manufacturer, manufacturer_designation,"
            "   manufacturer_designation__short, manufacturer_number,"
            "   moster_number, net_price, cutting, date_create)"
            " VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
            [
                BARCODE,
                self.USER,
                SORT_NUMBER,
                MANUFACTURER,
                MANUFACTURER_DESIGNATION,
                MANUFACTURER_DESIGNATION__SHORT,
                MANUFACTURER_NUMBER,
                MOSTER_NUMBER,
                NET_PRICE,
                CUTTING,
                date.today(),
            ],
        )
Also hauptsächlich ein bisschen mehr Formatierung für das SQL um das leichter lesen zu können.

Wobei ich ja bei relationalen Datenbanken SQLAlchemy bevorzuge, da würde das dann (ohne ORM) so aussehen:

Code: Alles auswählen

        self.engine.execute(
            DATANORM_TABLE.insert().values(
                barcode=BARCODE,
                user_name=self.USER,
                sort_number=SORT_NUMBER,
                manufacturer=MANUFACTURER,
                manufacturer_designation=MANUFACTURER_DESIGNATION,
                manufacturer_designation__short=MANUFACTURER_DESIGNATION__SHORT,
                manufacturer_number=MANUFACTURER_NUMBER,
                moster_number=MOSTER_NUMBER,
                net_price=NET_PRICE,
                cutting=CUTTING,
                date_create=date.today(),
            )
        )
Die Schreibweise hat unter anderem den Vorteil das man leicht sieht welcher Wert zu welcher Spalte gehört und man nicht anfangen muss Spaltennamen zu zählen und dann Werte zu zählen um zu sehen ob Spaltenname und Wert im Code zusammenpassen. Weiterer Vorteil: Es ist egal welche Platzhalter die Datenbankanbindung verwendet.
“Vir, intelligence has nothing to do with politics!” — Londo Mollari
Kalysto
User
Beiträge: 117
Registriert: Freitag 14. April 2017, 15:28

Ich danke euch beiden @Sirius3 und @__blackjack__ erst einmal für eure Antwort.

Ja, das problem mit dem "verzählen" kenne ich all zu gut.... nervig und lästig :(
Zu der Formatierung da schimmert es mir nun auch wieso ich da hin und wieder Probleme hatte gerade wenn es um 'NULL' Einträge ging....
diese musste ich immer statt: so schreiben: sonst hatte er mir immer 'NULL' eingetragen als reinen Text....

zu deiner Anmerkung @__blackjack__ mit SQLAlchemy das sieht auch schön und leicht zu Pflegen aus.
was müsste ich denn alles umbauen das ich diese Form verwenden könnte habe alles in der art aufgebaut wie es oben zu sehen ist....

Mit weiteren abfragen wie diesen:

Code: Alles auswählen

self.cur.execute("SELECT COUNT(*) FROM information_schema.tables WHERE `table_schema` LIKE '%{}%'".format(Customer_table))

self.cur.execute("CREATE TABLE IF NOT EXISTS -.........")

self.cur.execute("SELECT COUNT(*) FROM information_schema.tables WHERE `table_schema` = 'EE-7E4-3744__{}' AND `table_name` = '{}'".format(Customer_table, Customer_Project))
checkTable = self.cur.fetchone()[0]
Wäre das auch möglich mit deiner Variante ( SQLAlchemy ) @__backjack__ ?
und welche Importe wären hier notwendig ?
Benutzeravatar
__blackjack__
User
Beiträge: 14054
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Kalysto: Die drei Anfragen wären auch mit SQLAlchemy möglich. Letztlich kann man notfalls auch mit SQLAlchemy noch ”rohe” selbst geschriebene SQL-Abfragen machen. Aber das ginge alles auch ohne. Beispielsweise so:

Code: Alles auswählen

...
METADATA = MetaData()

TABLES_TABLE = Table(...)

USER_TABLE = Table(
    "user",
    METADATA,
    Column("id", INTEGER, primary_key=True),
    Column("login", CHAR(8), nullable=False, unique=True),
    Column("last_login_at", TIMESTAMP),
    # ...
)


...

        count = self.engine.scalar(
            select([func.count("*")]).where(
                TABLES_TABLE.c.table_schema.like(f"%{customer_table}%")
            )
        )

        USER_TABLE.create(self.engine, checkfirst=True)

        check_table = self.engine.scalar(
            select([func.count("*")]).where(
                and_(
                    TABLES_TABLE.c.table_schema
                    == "EE-7E4-3744__" + customer_table,
                    TABLES_TABLE.c.table_name == customer_project,
                )
            )
        )
Wobei ich mich beim letzten Beispiel frage wozu das gut sein soll. Falls das einfach nur ein Test auf vorhandensein der Tabelle werden soll, das ginge einfacher:

Code: Alles auswählen

        has_table = self.engine.has_table(
            customer_project, "EE-7E4-3744__" + customer_table
        )
Wobei man bei diesen Beispielen so einiges variieren kann. Ich habe beispielsweise ein `Engine`-Objekt verwendet wo man auch Verbindungsobjekte hätte verwenden können, und konstante, im Quelltext definierte Tabellenobjekte wo man, zumindest im ersten und letzten Fall vielleicht auch die Datenbank nach diesen Daten hätte fragen können (Reflection-API).

Und ich verwende die SQLAlchemy-Core-API — eventuell macht es auch Sinn das ORM zu verwenden.
“Vir, intelligence has nothing to do with politics!” — Londo Mollari
Kalysto
User
Beiträge: 117
Registriert: Freitag 14. April 2017, 15:28

Hallo __blackjack__,

Also ich muss vorweg sagen das ich das ganze auf einem iPhone Betriebe über die App - Pythonista.
D.h. Ich kann nur Python basierende Module verwenden ich habe schon einmal mit SQLAlchemy eine Engine erstellen wollen:

Code: Alles auswählen

 from sqlalchemy import create_engine
engine = create_engine('postgresql://user:pass@ip:port/sqlalchemy')
Und bekomme folgende Meldung:

Code: Alles auswählen

 ModuleNotFoundError: No module named 'psycopg2'
Das hatte ich nachgefragt im Pythonista Forum und dort wurde gesagt das: psycopg2 teilweise andere Programmiersprachen verwendet „C“
Sodass ich hier schon einen Umweg gehen sollte/musste mit: pg8000

Nun weis ich eben nicht wie und ob das überhaupt gehen würde wenn ich pg8000 zur Verbindung verwenden würde statt das von SQLAlchemy....
Weist du das zufällig ob das überhaupt Sinn machen weiter zu testen mit SQLAlchemy oder ob ich meinen Code einfach nur anpassen sollte mit den bsp. Von @Sirius3 und @__blackjack__ (dir)
Benutzeravatar
__blackjack__
User
Beiträge: 14054
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

pg8000 kann man verwenden: https://docs.sqlalchemy.org/en/14/diale ... sql.pg8000

Ob es sich am Ende für Dich lohnt SQLAlchemy zu verwenden kann man schlecht sagen. Das müsstest Du schon selbst evaluieren. Mit Deinem konkreten Anwendungsfall.
“Vir, intelligence has nothing to do with politics!” — Londo Mollari
Kalysto
User
Beiträge: 117
Registriert: Freitag 14. April 2017, 15:28

Kann man denn sagen ab wann es Sinn machen würde alles zu ändern ?
Habe ein paar Anfragen in meinem Code ^^

Oder ab wann würdest du es verwenden ?
Benutzeravatar
__blackjack__
User
Beiträge: 14054
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Kalysto: Ich persönlich verwende es eigentlich immer, aber dann halt auch von Anfang an. In der Regel dann auch das ORM. Und ich mache ein paar Sachen nicht die Du zu machen scheinst (Daten in Schema oder Tabellennamen kodieren).
“Vir, intelligence has nothing to do with politics!” — Londo Mollari
Kalysto
User
Beiträge: 117
Registriert: Freitag 14. April 2017, 15:28

Ich glaube ich werde meine Abfragen etc. So lassen nur das ich die Anpassungen machen werde welche ihr mir gegeben habe einmal ohne das Formatieren und mit den ? Als Platzhalter..
Die abfragen wie ich sie nun habe haben schon lang genug gedauert heraus zu bekommen (für meine Verhältnisse).

Ich danke dir aber für deine Hilfe @__blackjack__
Kalysto
User
Beiträge: 117
Registriert: Freitag 14. April 2017, 15:28

Eine Frage noch

wenn ich nun folgendes machen möchte:

Code: Alles auswählen

INSERT INTO ? ....
wie mache ich das ?
ich bekomme immer die Meldung meine Syntax sei falsch...

p.s.: bei mysql.connector muss ich %s anstatt ? verwenden.
Benutzeravatar
__blackjack__
User
Beiträge: 14054
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Kalysto: Das macht man eigentlich gar nicht weil Variable Tabellennamen auf einen Entwurfsfehler hindeuten, denn dann stecken Daten in Bezeichnern, die eigentlich in die Tabelle(n) gehören.
“Vir, intelligence has nothing to do with politics!” — Londo Mollari
Kalysto
User
Beiträge: 117
Registriert: Freitag 14. April 2017, 15:28

@__blackjack__,

Okay... und wie würdest du dies denn dann machen ich habe aktuell diese Struktur:

Code: Alles auswählen

- Haupt Ordner
    - Daten DB
        - customers (Tabelle)
        - datanorm (Tabelle)
        - manufacturers (Tabelle)
        - users (Tabelle)
        - version (Tabelle)
so und für jeden Kunde (customer) den ich erstelle erstelle ich mir eine Leere Datenbank mit dem Status und dem Kundenprojekt:

Code: Alles auswählen

- Haupt Ordner
    - Daten DB
        - customers (Tabelle)
        - datanorm (Tabelle)
        - manufacturers (Tabelle)
        - users (Tabelle)
        - version (Tabelle)
    - KUDNEN NAME
    	- $STATUS
    	- Kunden Projekt
    	- Kunden Projekt
    - KUDNEN NAME
    	- $STATUS
    	- Kunden Projekt
    	- Kunden Projekt
    	- Kunden Projekt
so war mein Gedanke dahinter und das ging auch die ganze zeit mit dem Formatieren wie ich es ja nun nicht mehr machen soll was ich gerade am bearbeiten bin.
daher wollte ich das nun auch wieder so machen aber das geht nicht weil ich den Fehler bekomme

wie könnte denn so etwas aussehen ?
wenn du verstanden hast was ich mache und vorhabe ?

danke.
Benutzeravatar
__blackjack__
User
Beiträge: 14054
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Kalysto: Ich verstehe die Hierarchie nicht so ganz, denn eine DB hat ja nur Tabellen und keine Ordner.

Wenn Du pro Kunde Tabellen anlegst die andere Namen aber die gleiche Struktur haben, dann würde man diese Tabellen *einmal* anlegen und der Kunde ist eine Spalte in diesen Tabellen.
“Vir, intelligence has nothing to do with politics!” — Londo Mollari
Sirius3
User
Beiträge: 18274
Registriert: Sonntag 21. Oktober 2012, 17:20

Genau das ist ein der angesprochene Datenbank-Designfehler. Wie willst Du z.B. eine Abfrage machen, welcher Kunde die meisten Projekte hat?

Die Lösung ist, eine Tabelle Projekte zu haben und jeder Eintrag hat eine Kunden_ID.
Und Du hast eine Tabelle Status, wieder mit der Kunden_ID.
Und eine Tabelle, wo Du die Daten für die Projekte speicherst, hat eine Projekt_ID.
Kalysto
User
Beiträge: 117
Registriert: Freitag 14. April 2017, 15:28

@__blackjack__,

das ist ein Benutzerordner mein Mysql-Server auf der Synology NAS legt das so an ^^ was nicht verkehrt ist ;)
also Haupt Ordner ist eig. ein Benutzer Name.

also so etwa:

Code: Alles auswählen

- Benutzername (Synology)
    - Daten DB
        - customers (Tabelle)
        - datanorm (Tabelle)
        - manufacturers (Tabelle)
        - users (Tabelle)
        - version (Tabelle)
    - Kundentabelle
        - $STATUS (einmalig für alle Kunden ?)
        (Für jedes Kundenprojekt eine Projekttabelle)
        - Umbau Küche
    	- Kunden Projekt
    	- Kunden Projekt
    	- Kunden Projekt
    	- Kunden Projekt
    	- Kunden Projekt
    	- Kunden Projekt
    	- Kunden Projekt
    	- Kunden Projekt
aber wie würde ich dann - Kunden Projekt ansprechen das ist ja Individuell ? wie z.b. Umbau Küche etc...
das $STATUS und Kundentabelle wäre somit fix für alle...
Kalysto
User
Beiträge: 117
Registriert: Freitag 14. April 2017, 15:28

Sirius3 hat geschrieben: Samstag 20. März 2021, 18:16 Genau das ist ein der angesprochene Datenbank-Designfehler. Wie willst Du z.B. eine Abfrage machen, welcher Kunde die meisten Projekte hat?

Die Lösung ist, eine Tabelle Projekte zu haben und jeder Eintrag hat eine Kunden_ID.
Und Du hast eine Tabelle Status, wieder mit der Kunden_ID.
Und eine Tabelle, wo Du die Daten für die Projekte speicherst, hat eine Projekt_ID.
Gut aber bei mir wäre in dem Projekt Materialien was ich für den Kunden benötige..
da wird doch irgend wann die abfrage zeit relativ lang ?
deswegen wollte ich Pro Kunde und pro Projekt eine DB und Tabelle erstellen.

das ist dann aber der Falsche weg ?
Sirius3
User
Beiträge: 18274
Registriert: Sonntag 21. Oktober 2012, 17:20

Wie viele Millionen Projekte hast Du denn? Nein, mit den passenden Indizes sind Abfragen sehr schnell.
Also hast Du eine Tabelle Material, mit den Spalten ID, Projekt_ID, Material_ID, Menge, ...
Eine Tabelle Projekt mit den Spalten Projekt_ID, Kunden_ID, Projektname, ...
Benutzeravatar
__blackjack__
User
Beiträge: 14054
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Kalysto: Wie das DBMS seine Daten physisch in Dateien organisiert geht Dich nix an. Das kann sich bei einem Update der Datenbanksoftware auch radikal ändern, denn die Schnittstelle zur Datenbank ist SQL. Ob das nun in Ordnern pro Datenbank und Datei pro Tabelle ist, oder eine komplette Datenbank in einer Datei, oder einzelne Tabellen über mehrere Ordner und Dateien verteilt, oder insgesamt nur eine Datei, oder ein Verzeichnis wo tausende von Dateien drin liegen die genau ein Megabyte gross sind, oder ob die Datenbank einfach eine leere Partition bekommt und da alles ohne Dateisystem selbst organisiert, ist völlig egal wenn man Relationen entwirft.

SQL sieht vor, dass Daten *in* Tabellen gespeichert sind und nicht im Schema, also nicht in Tabellennamen. Das Schema ist fest. Da kommen im laufenden Betrieb keine Tabellen hinzu und es fallen auch keine weg. Das passiert nur bei Versionsupdates der Software wenn man etwas am Schema ändern musste weil sich grundsätzlich etwas an der Struktur geändert hat. Nicht weil ein Kunde oder ein Projekt dazu gekommen oder weggefallen ist.
“Vir, intelligence has nothing to do with politics!” — Londo Mollari
Kalysto
User
Beiträge: 117
Registriert: Freitag 14. April 2017, 15:28

Okay dann danke ich euch beiden nochmal für die Infos dann muss ich das alles nochmal überarbeiten.
und schauen das ich das mit "festen" Tabellen machen werden und das über Kunden und Projekt ID`s machen werde.

eine Frage noch ich habe mir eine Funktion erstellt welche alle 5 Min eine SELECT Abfrage aufgibt sodass der Server nicht "einschläft" kann man das so machen ? oder gibts hier eine schönere Methode im mysql.connector ?
Antworten