txt->df->MS Server DB Fehler: column does not allow nulls

Installation und Anwendung von Datenbankschnittstellen wie SQLite, PostgreSQL, MariaDB/MySQL, der DB-API 2.0 und sonstigen Datenbanksystemen.
Antworten
MrBrown
User
Beiträge: 5
Registriert: Freitag 23. April 2021, 09:48

Hallo Zusammen , ich arbeite seit einigen Tagen mit Python , bin also noch ein blutiger Anfänger - letztlich soll durch pm2 mit einem Python Skript, eine Datenpunpe erzeugt werden :-) - erhoffe mir eine kleine Hilfestellung zu folgender Fehlermeldung.

Fehlermeldung:
" File "c:/testpumpe/Funktionen für MS DB und Auslesen/s1_s2_auf_db.py", line 38, in <module>
cursor.execute("INSERT INTO XXX.dbo.[RAW-TEST-1] (s2, s3, s4, s5, s6, s7, s8, s9, s10, s11) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", (s1, s2, s3, s4, s5, s6, s7, s8, s9, s10))
pyodbc.IntegrityError: ('23000', "[23000] [Microsoft][ODBC SQL Server Driver][SQL Server]Cannot insert the value NULL into column 'id', table
'XXX.dbo.RAW-TEST-1'; column does not allow nulls. INSERT fails. (515) (SQLExecDirectW); [23000] [Microsoft][ODBC SQL Server Driver][SQL Server]The statement has been terminated. (3621)")"

Habe schon verschiedene Insert Befehle ausprobiert, bisher leider ohne Erfolg. Irgendwie mag die DB meine variablen nicht aufnehmen. s2 sollte auch kein ID feld sein.

Vielen Dank an jeden der sich Zeit für eine konstruktive Antwort/Kritik nimmt.

typische Zeile der *txt
3005584465;2855422-13;122264665226;0730;29.01.21;21:13:02;31.36;okay;;

Code:
import numpy as np
import pandas as pd
import pyodbc

server = 'xxx'
database = 'xxx'
username = 'xxx'
password = 'xxx'
cnxn = pyodbc.connect('DRIVER={SQL Server};SERVER='+server+';DATABASE='+database+';UID='+username+';PWD='+ password)

df = pd.read_csv("back_full_mp29012021.txt",
sep=";",
header=None
)

df.columns = ["Auftragsnummer", "Materialnummer", "Seriennummer", "Prüfplatz","Datum","Uhrzeit","Prüfzeit","Status","Fehler","Messung"]
print (df)

#z - Zeile
z = 0
for row in df.itertuples():

s1=str(df['Auftragsnummer'][z])
s2=str(df['Materialnummer'][z])
s3=str(df['Seriennummer'][z])
s4=str(df['Prüfplatz'][z] )
s5=str(df['Datum'][z] )
s6=str(df['Uhrzeit'][z])
s7=str(df['Prüfzeit'][z])
s8=str(df['Status'][z])
s9=str(df['Fehler'][z])
s10=str(df['Messung'][z])

cursor = cnxn.cursor()
#Rest to_do _ ggf noch Fehlermeldungen abschneiden wegen String mit 50 Zeichen?
#cursor.execute("INSERT INTO xxx.dbo.[RAW-TEST-1] (s2, s3, s4, s5, s6, s7, s8, s9, s10, s11) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s)", (s1, s2, s3, s4, s5, s6, s7, s8, s9, s10))

cursor.execute("INSERT INTO xxx.dbo.[RAW-TEST-1] (s2, s3, s4, s5, s6, s7, s8, s9, s10, s11) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", (s1, s2, s3, s4, s5, s6, s7, s8, s9, s10))

#cursor.execute("""INSERT INTO xxx.dbo.[RAW-TEST-1] (s2, s3, s4, s5, s6, s7, s8, s9, s10, s11)
#VALUES ({},{},{},{},{},{},{},{},{},{})".format(s1, s2, s3, s4, s5, s6, s7, s8, s9, s10)""")
#cursor.execute("INSERT INTO xxx.dbo.[RAW-TEST-1] (s3,s4,s5,s6,s7,s8,s9,s10,s11,s12) values(?,?,?,?,?,?,?,?,?,?)", s1, s2, s3, s4, s5, s6, s7, s8, s9, s10)

#cursor.execute("""INSERT INTO xxx.dbo.[RAW-TEST-1] (s2, s3, s4, s5, s6, s7, s8, s9, s10, s11)
#VALUES ("{s1}", "{s2}", "{s3}", "{s4}","{s5}","{s6}","{s7}","{s8}","{s9}","{s10}");""")

cnxn.commit()
cursor.close()



z=z+1 # Mit Z arbeiten für Prüfung auf neue Zahlen => in *.txt speichern und zu Beginn Zeilen zählen! Bei erolgreichem einfügen....
Sirius3
User
Beiträge: 17711
Registriert: Sonntag 21. Oktober 2012, 17:20

Wenn Du SQLAlchemy benutzt, kann Pandas direkt in SQL-Tabellen schreiben.

Statt Strings mit + zusammenzustückeln, benutzt man Formatstrings. Bei ODBC gibt es glaube ich auch noch eine Möglichkeit, die Parameter richtig zu übergeben, da müßtest Du nochmal danach suchen.
Benutze keine kryptischen Abkürzungen, warum cnxn statt connection und woher kommt das x?
Beim lesen aus CSV gibt man die Spaltenbeschriftung gleich direkt an.

Es ist unsinnig, itertuples zu benutzen, wenn man dann per Index auf die Daten zugreift. Also der Zugriff über einen Index ist unsinn.
Man darf auch nicht alle Spalten in Strings umwandeln, denn dann umgeht man ja die Typprüfung der Datenbankanbindung.
Für das Eintragen aller Datensätze würde man einen Cursor verwenden und nicht für jeden Eintrag einen neuen.
Die Spaltennamen sind sehr schlecht gewählt. Warum heißen die s2 bis s11? Und warum nennst Du dann Deine Parameter s1 bis s10?
Der Tabellenname ist auch nicht besser.

Code: Alles auswählen

from contextlib import closing
import pandas as pd
import pyodbc 

server = 'xxx' 
database = 'xxx'
username = 'xxx' 
password = 'xxx' 
connection = pyodbc.connect(f'DRIVER={SQL Server};SERVER={server};DATABASE={database};UID={username};PWD={password}')

df = pd.read_csv("back_full_mp29012021.txt", sep=";", names=["Auftragsnummer", "Materialnummer", "Seriennummer", "Prüfplatz","Datum","Uhrzeit","Prüfzeit","Status","Fehler","Messung"])
print(df) 

with closing(connection.cursor()) as cursor:
    for row in df.itertuples():
        cursor.execute("INSERT INTO xxx.dbo.[RAW-TEST-1] (s2, s3, s4, s5, s6, s7, s8, s9, s10, s11) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", (
            row.Auftragsnummer,
            row.Materialnummer,
            row.Seriennummer,
            row.Prüfplatz,
            row.Datum,
            row.Uhrzeit,
            row.Prüfzeit,
            row.Status,
            row.Fehler,
            row.Messung,
        ))
        
connection.commit()
Und wenn Du irgendwo die Fehlermeldung bekommst, dass Du versuchst NULLen in die Tabelle einzutragen, dann wohl deshalb, weil Du nicht alle Spalten angegeben hast, die fehlenden also mit NULL gefüllt werden.
MrBrown
User
Beiträge: 5
Registriert: Freitag 23. April 2021, 09:48

Hey - danke für die Antwort - hat mir sehr geholfen ein gutes Stück voran zu kommen.

Wenn Du SQLAlchemy benutzt, kann Pandas direkt in SQL-Tabellen schreiben.
SQLAlchemy habe ich betrachtet, bin aber bisher an den Einstellungen der Engine gescheitert

Statt Strings mit + zusammenzustückeln, benutzt man Formatstrings. Bei ODBC gibt es glaube ich auch noch eine Möglichkeit, die Parameter richtig zu übergeben, da müßtest Du nochmal danach suchen.
Steht jetzt an

Benutze keine kryptischen Abkürzungen, warum cnxn statt connection und woher kommt das x?
Beim lesen aus CSV gibt man die Spaltenbeschriftung gleich direkt an.

Check

Es ist unsinnig, itertuples zu benutzen, wenn man dann per Index auf die Daten zugreift. Also der Zugriff über einen Index ist unsinn.
Stimme zu, dann brauch ich auch keine Dataframes nutzen - zählt wohl zu einem Irrweg im Rahmen von learning by doing

Man darf auch nicht alle Spalten in Strings umwandeln, denn dann umgeht man ja die Typprüfung der Datenbankanbindung.
Das muss ich noch testen

Für das Eintragen aller Datensätze würde man einen Cursor verwenden und nicht für jeden Eintrag einen neuen.
Danke hier war ich mir sehr unsicher

Die Spaltennamen sind sehr schlecht gewählt. Warum heißen die s2 bis s11? Und warum nennst Du dann Deine Parameter s1 bis s10?
Das war den Versuchen geschuldet, dem ID-Feld auszuweichen (was aber nicht ging, da ich es setzen muss) - lösen konnte ich das Problem durch einen korregierten Insert

cursor.execute("INSERT INTO xxx.[RAW-TEST-1] ( id, s1, s2, s3, s4, s5, s6, s7, s8, s9, s10) VALUES ( ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"

und

df.index = [x for x in range(1, len(df.values)+1)]
df.index.name = 'id'

Der Tabellenname ist auch nicht besser.
sehe ich auch so, hat mir direkt zu Beginn Schwierigkeiten bereitet, habe aber nur lese und schreibrechte für vorhandene Tabellen


______________next___________
Werde später nochmal den aktuellen Code vorzeigen, möchte aber erst noch ein paar Sachen machen, beschäftige mich jetzt mit Headern, habe gestern einen Vergleich der DB Daten mit der *txt Quelle erstell und erzeuge daraus dann einen neuen df mit den neuen Inhalten

x=len(df1)
y=len(df2)
df_new=df2.iloc[x:y,:]

Bis bald - wollt nicht noch länger mit einer Antwort warten - auch wenn jetzt noch keine konkrete Frage vorhanden ist.

Grüße
Mr.Brown
MrBrown
User
Beiträge: 5
Registriert: Freitag 23. April 2021, 09:48

Funktioniert wie gewollt, 2 offene Kritikpunkte sind vorhanden, dass ich nicht mit Formatstrings arbeite und dass alle Werte bis auf die ID zu Strings gewandelt werden.

Fragen die ich mir momentan stelle:

- ist das Dateien kopieren, um andere Schreibprozesse in den Quelledaten nicht zu blockieren die beste Lösung?
- Kann man unbesorgt, den Dataframe aus der DB laden für den Vergleich auf neue Inhalte ? Wie wird eine DB Last ermittelt ?

sorry für a,b,c,d,e :-) - hier sind für sich sprechende Variablennamen zu finden.

Code: Alles auswählen

import pandas as pd
import pyodbc 
import numpy as np
import shutil
import os
from pathlib import Path
from contextlib import closing

# Zielverzeichnisse und Daten
# zuletzt in die DB geschrieben Daten und Zielverzeichnis
a="xxx/kopie_prozessdaten.txt"
#Quelle für neue Inhalte
b="xxx/back_full_mp29012021.txt"
#Zielverzeichnis für Kopie der Datei mit neuen Inhalten für Vergleich im nächsten Durchlauf
c="xxx/kopie_prozessdaten_2.txt"
#Prozessdaten - Verzeichnis
d='xxx/quelle'

#Path ist hier eine FKT - nachfolgend eine Variable, ggf VAr namen ändern sonst irreführend

def header(msg):
    print ('-' * 50)
    print ('[' +msg+ ' ]')

def db_eintrag(df):
    header("fkt aufruf")
    print (df)

def in_DB_schreiben (df):
    ##### pyodbc  - DB Verbindung aufbauen ######
    server = 'xxx' 
    database = 'xxx'
    username = 'xxx' 
    password = 'xxx' 
    connection = pyodbc.connect('DRIVER={SQL Server};SERVER='+server+';DATABASE='+database+';UID='+username+';PWD='+ password)

    #################   Typänderungern  #################################
    df = df.astype(np.str)


    with closing(connection.cursor()) as cursor:
        for row in df.itertuples():
            cursor.execute("INSERT INTO xxx.[RAW-TEST-1] ( id, s1, s2, s3, s4, s5, s6, s7, s8, s9, s10) VALUES ( ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", (
   	        row.Index,
                row.Auftragsnummer,
                row.Materialnummer,
                row.Seriennummer,
                row.Prüfplatz,
                row.Datum,
                row.Uhrzeit,
                row.Prüfzeit,
                row.Status,
                row.Fehler,
                row.Messung,
            ))
        
    connection.commit()

def extrahiere_neue_inhalte(a,b,c,d):
    #fname = Path("C:/testpumpe/Funktionen für MS DB und Auslesen/final_test/kopie_prozessdaten.txt") 
    fname = Path(a) 

    # Wenn kopie_prozessdaten vorhanden, auf neuen Inhalt prüfen
    if fname.is_file():
        # Prozessdaten Netzlaufwerk zbsp.
        path = d 
        # Quelldatei 
        source = b
        # Ziellverzeichnisse
        destination = a
        destination2 = c
        #Inhalt ins Ziel kopieren (netz->lokae txt)
        dest = shutil.copy(source, destination) 
        # df1  - alte Dataframe aus vorherigem Durchlauf (if fname.is.file())   
        df1 = pd.read_csv(c, sep=";", names=["Auftragsnummer", "Materialnummer", "Seriennummer", "Prüfplatz","Datum","Uhrzeit","Prüfzeit","Status","Fehler","Messung"])
        df1.index = [x for x in range(1, len(df1.values)+1)]
        df1.index.name = 'id'
        df1 = df1.astype(np.str)
        #df2 - neuen Inhalte aus Netzlaufwerk
        df2 = pd.read_csv(a, sep=";", names=["Auftragsnummer", "Materialnummer", "Seriennummer", "Prüfplatz","Datum","Uhrzeit","Prüfzeit","Status","Fehler","Messung"])
        df2.index = [x for x in range(1, len(df2.values)+1)]
        df2.index.name = 'id'
        df2 = df2.astype(np.str)
   
        x=len(df1)
        y=len(df2)

        if x == y:
            #keine neuen Inhalte
            header ("nix gewesen ausser spesen")
        else:
            
            header ("else2 hüpf - hier neuer df für DB")
            #neue Inhalte als Dataframe ansteuern und df erzeugen - nur auf Basis des Index
            df_new=df2.iloc[x:y,:]
            #in DB schieben
            db_eintrag (df_new)
            in_DB_schreiben(df_new)
            #Datei für Ablage und späteren Vergleich erzeugen - inaktiv atm weil sonst Inhalt gleich nach einmaligem ausführen...
            #dest = shutil.copy(destination, destination2) 
    
        #else - Wenn keine Datei vorhanden, erster Durchlauf - Datei komplett einfügen
    else:
        print("bisher kein Durchlauf, Daten komplett einfügen")
       
  
extrahiere_neue_inhalte (a,b,c,d)
MrBrown
User
Beiträge: 5
Registriert: Freitag 23. April 2021, 09:48

Hallo,

es hat sich eine Frage ergeben zu der ich keine Antwort finde.

Fall A:
Ausgeführt in VisualStuido+Anaconda wird die OrderNumber wie gewollt ausgegeben und auch in die DB geschrieben.

3009729770

Fall B:
Ausgeführt mit pm2+Anaconda via Powershell wird an die Bestellnummer noch ein ".0" angehangen und auch in die DB mitgeschrieben

3009729770.0

ggf. kann jmd helfen, bin mir aber nicht ganz sicher ob ich hierfür im richtigen Forum bin.

VG

Code: Alles auswählen

import pandas as pd
import pyodbc 
import numpy as np
import shutil
from shutil import copyfile
import os
from pathlib import Path
from contextlib import closing
from datetime import datetime, timedelta
import time
import copy

######################################################################
###############   Zielverzeichnisse und Daten   ######################
######################################################################
filename=time.strftime("%d%m%Y")#aktuelles Datum für Filename
DB_ist_txt='xxx\DB_ist_mp'+filename+'.txt'# zuletzt in die DB geschrieben Daten und Zielverzeichnis
RQS_txt='xxx\mp'+filename+'.txt'#Quelle für neue Inhalte
#RQS_txt='xxx\mp'+filename+'.txt'
RQS_tmp_txt='xxx\RQS_ist_mp'+filename+'.txt'#Zielverzeichnis für Kopie der Datei mit neuen Inhalten für Vergleuich im nächsten Durchlauf
######################################################################

def header(msg):
    print ('-' * 50)
    print ('[' +msg+ ' ]')

def in_DB_schreiben (df):
    ##### pyodbc  - DB Verbindung aufbauen ######
    server = 'xxxx' 
    database = 'xxxx'
    username = 'xxx' 
    password = 'xxx' 
    connection = pyodbc.connect('DRIVER={SQL Server};SERVER='+server+';DATABASE='+database+';UID='+username+';PWD='+ password)

    with closing(connection.cursor()) as cursor:
        for row in df.itertuples():
            cursor.execute("INSERT INTO xxxx.[RAW_xxx] (OrderNumber, MaterialNumber,MaterialName , SerialNumber,WorkingProcess,CountryID,Location,BusinessUnit, TestSystem, DateTime, TestDuration,  TestResult, ResultText_1, ResultText_2) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", 
            ( 
                row.OrderNumber,
                row.MaterialNumber,
                row.MaterialName,
                row.SerialNumber,
                row.WorkingProcess,
                row.CountryID,
                row.Location,
                row.BusinessUnit,
                row.TestSystem,
                row.DateTime,
                row.TestDuration,
                row.Test_Result,
                row.ResultText_1,
                row.ResultText_2,              
            ))
    print ("DB COMMIT")    
    connection.commit()

def df_anpassen_mpDB(df):
    df = copy.deepcopy(df) #neues Objekt erzeugen (liegt an Pandas arbeitsweise)
    df.insert(1, "CountryId", "xxx") 
    df.insert(2, "WorkingProcess", "TO_DO")
    df.insert(3, "Location", "xxx") 
    df.insert(4, "MaterialName", "TO_DO")
    df.insert(5, "BusinessUnit", "xxx")
    df['DateTime']=df['Datum']+ df['Uhrzeit']
    df['DateTime'] = pd.to_datetime(df['DateTime'], format='%d.%m.%y%H:%M:%S')
    del df['Datum']
    del df['Uhrzeit']
    df = df.reindex(columns=['OrderNumber', 'MaterialNumber','MaterialName','SerialNumber','WorkingProcess','CountryID','Location','BusinessUnit', 'TestSystem', 'DateTime', 'TestDuration', 'Test_Result', 'ResultText_1', 'ResultText_2'])#converters={'Prüfzeit': decimal_from_value}
    #Typ anpassungen
    df['CountryID'] = df['CountryID'].astype(str)
    df['WorkingProcess'] = df['WorkingProcess'].astype(str)
    df['Location'] = df['Location'].astype(str)
    df['MaterialName'] = df['MaterialName'].astype(str)
    df['BusinessUnit'] = df['BusinessUnit'].astype(str)
    print (df.dtypes)
    #df['OrderNumber'] = df['OrderNumber'].astype(long)
    df['OrderNumber'] = df['OrderNumber'].astype(str)
    print (df)
    df['MaterialNumber'] = df['MaterialNumber'].astype(str)
    #df['SerialNumber'] = df['SerialNumber'].astype(str)
    #df['TestDuration'] = df['TestDuration'].astype(float)
    df['TestSystem'] = df['TestSystem'].astype(str)
    df['Test_Result'] = df['Test_Result'].astype(str)
    df['ResultText_1'] = df['ResultText_1'].astype(str)
    df['ResultText_2'] = df['ResultText_2'].astype(str)
    print (df)
    header ("df angepasst für MP Tabelle -> in_DB_schreiben()")
    print (df.dtypes)
    in_DB_schreiben (df)    

def extrahiere_neue_inhalte(DB_ist_txt,RQS_txt,RQS_tmp_txt):
    fname = Path(DB_ist_txt) 
    print (DB_ist_txt)
    print (datetime.now().strftime('%Y-%m-%d %H:%M:%S'))

    if fname.is_file():
        # Prozessdaten Netzlaufwerk zbsp.
        copyfile(RQS_txt, RQS_tmp_txt)
        # df1  neue Datei aus RQS  
        df1 = pd.read_csv(RQS_tmp_txt, sep=";", encoding="ISO-8859-1", names=["OrderNumber", "MaterialNumber", "SerialNumber", "TestSystem", "Datum","Uhrzeit", "TestDuration", "Test_Result", "ResultText_1", "ResultText_2"])
        df1.index = [x for x in range(1, len(df1.values)+1)]
        df1.index.name = 'id'
        df1 = df1.astype(object).replace(np.nan, '')
            
        #df2 - lokale&DB Einträge (heute)
        df2 = pd.read_csv(DB_ist_txt, sep=";", encoding="ISO-8859-1", names=["OrderNumber", "MaterialNumber", "SerialNumber", "TestSystem", "Datum","Uhrzeit", "TestDuration", "Test_Result", "ResultText_1", "ResultText_2"])
        #df2 = pd.read_csv(DB_ist_txt, sep=";", encoding="ISO-8859-1", names=["OrderNumber", "MaterialNumber", "SerialNumber", "WorkingProcess", "TestSystem", "DateTime", "TestDuration", "Test_Result", "ResultText1"])
        df2.index = [x for x in range(1, len(df2.values)+1)]
        df2.index.name = 'id'
        df2 = df2.astype(object).replace(np.nan, '')
      
        x=len(df1) 
        y=len(df2)
        print (x)
        print(y)
  
        if x == y:
            #keine neuen Inhalte
            header ("KEINE NEUEN DATEN")
        else:
            header ("DATEN FÜR DB")
            #df_new=df1.iloc[y:x,:]
            df_new=df1.iloc[y:x,:]
            copyfile(RQS_tmp_txt, DB_ist_txt)
            df_anpassen_mpDB(df_new)       
                        
    else:
        header("Keine DB_ist_txt für Heute vorhanden")         
        d = datetime.today() - timedelta(days=1)
        filename2=d.strftime("%d%m%Y")
        RQS_tmpold='xxx\RQS_ist_mp'+filename2+'.txt'
        #RQS_old='xxx\mp'+filename2+'.txt'
        RQS_old='xxx\mp'+filename2+'.txt'
        DB_istold='xxxx\DB_ist_mp'+filename2+'.txt'
        fname2 = Path(DB_istold)
        fname3 = Path(RQS_txt)
        if fname2.is_file():
            header("gestrige Daten auf Vollständigkeit prüfen")
            extrahiere_neue_inhalte (DB_istold,RQS_old, RQS_tmpold)
            
            if fname3.is_file(): # Wenn RQS für Heute vorhanden, komplett einfügen...
                    copyfile(RQS_txt, DB_ist_txt)
                    df3 = pd.read_csv(DB_ist_txt, sep=";", encoding="ISO-8859-1", names=["OrderNumber", "MaterialNumber", "SerialNumber", "TestSystem", "Datum","Uhrzeit", "TestDuration", "Test_Result", "ResultText_1", "ResultText_2"])
                    df3.index.name = 'id'
                    df3 = df3.astype(object).replace(np.nan, '')
                    header ("Erste Durchgang auf Daten111 - komplett einfügen:")
                    print(RQS_txt)
                    df_anpassen_mpDB (df3)
        else:
              if fname3.is_file(): #Wenn RQS für Heute vorhanden...nochmal durchdenken, ist das geschickt ?!testen
                    if fname.is_file(): #Wenn DB_ist_txt für Heute vorhanden
                        header("DB Einträge für Gestern vorhanden")
            
                    else:
                        
                        copyfile(RQS_txt, DB_ist_txt)
                        df3 = pd.read_csv(DB_ist_txt, sep=";", encoding="ISO-8859-1", names=["OrderNumber", "MaterialNumber", "SerialNumber", "TestSystem", "Datum","Uhrzeit", "TestDuration", "Test_Result", "ResultText_1", "ResultText_2"])
                        df3.index.name = 'id'
                        df3 = df3.astype(object).replace(np.nan, '')
                        header ("Erste Durchgang auf Daten222:")
                        print(RQS_txt)
                        df_anpassen_mpDB (df3)
                        # eine fkt schaffen, mp_txt_komplett_einfügen => quasi der ganze block als fkt
        
header("MAIN:extrahiere_neue_inhalte (DB_ist_txt,RQS_txt,RQS_tmp_txt)")
extrahiere_neue_inhalte (DB_ist_txt,RQS_txt,RQS_tmp_txt)


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

Das `df1.astype(object)` ist definitiv falsch. Man wandelt nicht einfach alles in einem Dataframe in Objekte um, dazu sind Dataframes nicht gedacht.
Ich sehe 4 mal im Code den selben read_csv-Aufruf. Der sollte nur einmal zu finden sein. Auch der Rest sieht stark nach kopiertem Code aus.
An Deinen Dateinamen-Konstanten solltest Du arbeiten. \ ist ein Sonderzeichen. Pfade trennt man mit /. Du benutzt schon Teilweise pathlib.Path, das solltest Du für alle Dateinamen machen und benutzt nicht + um im letzten Teil des Pfades das Datum einzubauen, sondern Formatstrings.

Um die Datums- und Uhrzeitspalten zusammenzufassen, gibt es eine passende Option bei read_csv. Das macht man nicht erst später in `df_anpassen_mpDB`.
Dieses ganze Umwandeln von einzelnen Spalten in Strings ist falsch. Die Werte sollten von Anfang an den richtigen Typ haben, und der muß dann nicht umgewandelt werden. Warum machst du das?
OrderNumber, MaterialNumber und vielleicht auch noch andere Spalten sollten Ganzzahlen sein, wie Du da jetzt wo Floats reinbringst, ist mir bei der ganzen Typumwandlung nicht klar. Dass Du das in Strings umwandelst, ist, wie schon geschrieben, falsch.
Den richtigen Datentyp gibt man bei read_csv an, und ändert den dann später auch nicht mehr.
MrBrown
User
Beiträge: 5
Registriert: Freitag 23. April 2021, 09:48

Das `df1.astype(object)` ist definitiv falsch. Man wandelt nicht einfach alles in einem Dataframe in Objekte um, dazu sind Dataframes nicht gedacht.
>>hatte eine Spalte keinen Wert, hat Pandas nan eingetragen, das wollte ich durch ein leeres Feld ersetzen (Wunsch vom DB-Owner)


Ich sehe 4 mal im Code den selben read_csv-Aufruf. Der sollte nur einmal zu finden sein. Auch der Rest sieht stark nach kopiertem Code aus.
>>ich arbeite jetzt seit einem Monat mit Python, natürlich ist viel kopiert

An Deinen Dateinamen-Konstanten solltest Du arbeiten. \ ist ein Sonderzeichen. Pfade trennt man mit /. Du benutzt schon Teilweise pathlib.Path, das solltest Du für alle Dateinamen machen und benutzt nicht + um im letzten Teil des Pfades das Datum einzubauen, sondern Formatstrings.
>>setz ich mich dann jetzt dran.

Um die Datums- und Uhrzeitspalten zusammenzufassen, gibt es eine passende Option bei read_csv. Das macht man nicht erst später in `df_anpassen_mpDB`.
>> habe ich nicht gefunden bei meiner Suche zum Thema DateTime

Dieses ganze Umwandeln von einzelnen Spalten in Strings ist falsch. Die Werte sollten von Anfang an den richtigen Typ haben, und der muß dann nicht umgewandelt werden. Warum machst du das?
>> Du meinst, ich sollt den dtytpe direkt bei read CSV einbauen ? Werde ich mich dann mal ebenfalls reinfuchsen.


OrderNumber, MaterialNumber und vielleicht auch noch andere Spalten sollten Ganzzahlen sein, wie Du da jetzt wo Floats reinbringst, ist mir bei der ganzen Typumwandlung nicht klar.
>> Wie oben beschrieben, ist es beim Ausführen auf meinem Laptop noch eine Ganzzahl, jedoch auf dem Rechner wo pm2 das Skript in endlosschleife ausführt wird ein .0 angehangen


Dass Du das in Strings umwandelst, ist, wie schon geschrieben, falsch.
Den richtigen Datentyp gibt man bei read_csv an, und ändert den dann später auch nicht mehr.
>> Ich kriege vom DB Owner vorgaben, welchen Datentyp ich verwenden soll je Spalte, für den DB Eintrag

Melde mich die Tage mit einer optimierten Variante Besten Dank so weit :) und ggf. noch einen Gedanken zur Fett markierten Anmerkung ?

VG
Antworten