Python
Pandas to_sql leicht beherrschen: Ein Leitfaden für Anfänger

Pandas to_sql leicht beherrschen: Ein Leitfaden für Anfänger

MoeNagy Dev

Eine Datenbankverbindung herstellen

Aufbau einer Datenbankverbindung

Um eine Datenbankverbindung mit Python herzustellen, kannst du die sqlalchemy Bibliothek verwenden, die eine einheitliche Schnittstelle zum Arbeiten mit verschiedenen Datenbank-Engines bietet. Hier ist ein Beispiel, wie du eine Verbindung zu einer PostgreSQL-Datenbank herstellst:

from sqlalchemy import create_engine
 
# Erstelle den Datenbank-Engine
engine = create_engine('postgresql://benutzername:passwort@host:port/databankenname')
 
# Teste die Verbindung
verbindung = engine.connect()
ergebnis = verbindung.execute('SELECT 1')
print(ergebnis.fetchone())

Ersetze in diesem Beispiel benutzername, passwort, host, port und datenbankenname durch deine tatsächlichen Datenbankanmeldeinformationen und Verbindungsdetails.

Konfiguration der Datenbankverbindung

Du kannst die Datenbankverbindung weiter konfigurieren, indem du zusätzliche Optionen angibst, wie z. B. die Größe des Verbindungspools, Timeout-Einstellungen und mehr. Hier ist ein Beispiel:

from sqlalchemy import create_engine
 
# Erstelle den Datenbank-Engine mit zusätzlicher Konfiguration
engine = create_engine('postgresql://benutzername:passwort@host:port/databankenname',
                       pool_size=20,
                       max_overflow=0,
                       pool_timeout=30,
                       pool_recycle=3600)
 
# Teste die Verbindung
verbindung = engine.connect()
ergebnis = verbindung.execute('SELECT 1')
print(ergebnis.fetchone())

In diesem Beispiel haben wir die Größe des Verbindungspools auf 20 gesetzt, Überschussverbindungen deaktiviert, den Timeout des Pools auf 30 Sekunden gesetzt und den Pool so konfiguriert, dass er alle Stunde Verbindungen recycelt.

Umgang mit Zugangsdaten zur Datenbank

Es ist wichtig, deine Datenbankzugangsdaten sicher aufzubewahren und zu vermeiden, sie direkt im Code fest einzugeben. Eine Möglichkeit, dies zu handhaben, besteht darin, die Zugangsdaten in Umgebungsvariablen zu speichern und sie zur Laufzeit zu laden. Hier ist ein Beispiel:

import os
from sqlalchemy import create_engine
 
# Lade die Datenbankzugangsdaten aus den Umgebungsvariablen
db_benutzer = os.getenv('DB_BENUTZER')
db_passwort = os.getenv('DB_PASSWORT')
db_host = os.getenv('DB_HOST')
db_port = os.getenv('DB_PORT')
db_name = os.getenv('DB_NAME')
 
# Erstelle den Datenbank-Engine
engine = create_engine(f'postgresql://{db_benutzer}:{db_passwort}@{db_host}:{db_port}/{db_name}')
 
# Teste die Verbindung
verbindung = engine.connect()
ergebnis = verbindung.execute('SELECT 1')
print(ergebnis.fetchone())

In diesem Beispiel laden wir die Datenbankzugangsdaten aus Umgebungsvariablen. Achte darauf, diese Umgebungsvariablen in deinem System zu setzen, bevor du den Code ausführst.

Daten für den Eintrag vorbereiten

Bereinigen und Formatieren von Daten

Bevor du Daten in eine Datenbank einfügst, ist es oft notwendig, die Daten zu bereinigen und zu formatieren. Dabei können Aufgaben wie das Entfernen von führenden und abschließenden Leerzeichen, das Handhaben von Datum-/Uhrzeitformaten und das Konvertieren von Datentypen enthalten sein. Hier ist ein Beispiel mit der pandas-Bibliothek:

import pandas as pd
 
# Lade die Daten in ein pandas DataFrame
df = pd.read_csv('daten.csv')
 
# Bereinige und formatiere die Daten
df['name'] = df['name'].str.strip()
df['date'] = pd.to_datetime(df['date'])
df['amount'] = df['amount'].astype(float)

In diesem Beispiel entfernen wir führende und abschließende Leerzeichen aus der Spalte 'name', konvertieren die Spalte 'date' in ein Datum-Zeit-Format und stellen sicher, dass die Spalte 'amount' als Fließkommazahl gespeichert wird.

Umgang mit fehlenden Werten

Fehlende Daten können Probleme verursachen, wenn Daten in eine Datenbank eingefügt werden. Du kannst pandas verwenden, um fehlende Werte auf verschiedene Arten zu handhaben, z. B. durch Löschen von Zeilen mit fehlenden Daten oder durch Auffüllen der fehlenden Werte. Hier ist ein Beispiel:

import pandas as pd
 
# Lade die Daten in ein pandas DataFrame
df = pd.read_csv('daten.csv')
 
# Handhabung von fehlenden Werten
df = df.dropna(subset=['name', 'date'])
df['amount'] = df['amount'].fillna(0)

In diesem Beispiel löschen wir alle Zeilen, in denen die Spalte 'name' oder 'date' einen fehlenden Wert hat, und füllen alle fehlenden Werte in der Spalte 'amount' mit 0 auf.

Sicherstellen, dass die Datentypen übereinstimmen

Es ist wichtig sicherzustellen, dass die Datentypen in deinem DataFrame mit den vom Datenbank erwarteten Datentypen übereinstimmen. Du kannst das dtypes-Attribut eines pandas DataFrame verwenden, um die Datentypen zu überprüfen, und die astype()-Methode verwenden, um sie gegebenenfalls zu konvertieren. Hier ist ein Beispiel:

import pandas as pd
 
# Lade die Daten in ein pandas DataFrame
df = pd.read_csv('daten.csv')
 
# Überprüfe die Datentypen
print(df.dtypes)
 
# Konvertiere die Datentypen bei Bedarf
df['date'] = df['date'].astype('datetime64[ns]')
df['amount'] = df['amount'].astype(float)

In diesem Beispiel stellen wir sicher, dass die Spalte 'date' als datetime64-Datentyp und die Spalte 'amount' als Float gespeichert wird.

Einfügen von Daten in eine Datenbank

Verwendung der pandas to_sql() Methode

Die pandas-Bibliothek bietet eine praktische Möglichkeit, Daten mithilfe der to_sql()-Methode in eine Datenbank einzufügen. Hier ist ein Beispiel:

import pandas as pd
from sqlalchemy import create_engine
 
# Lade die Daten in ein pandas DataFrame
df = pd.read_csv('daten.csv')
 
# Erstelle den Database-Engine
engine = create_engine('postgresql://benutzername:passwort@host:port/databankenname')
 
# Füge die Daten in die Datenbank ein
df.to_sql('tabellenname', engine, if_exists='append', index=False)

In diesem Beispiel verwenden wir die to_sql()-Methode, um die Daten aus dem DataFrame in eine Tabelle mit dem Namen tabellenname einzufügen. Der Parameter if_exists gibt an, was zu tun ist, wenn die Tabelle bereits existiert (in diesem Fall fügen wir die Daten hinzu).

Angeben des Tabellennamens

Bei Verwendung der to_sql()-Methode kannst du den Namen der Tabelle angeben, in die die Daten eingefügt werden sollen. Hier ist ein Beispiel:

import pandas as pd

from sqlalchemy import create_engine

Die Daten in ein pandas DataFrame laden

df = pd.read_csv('data.csv')

Die Datenbank-Engine erstellen

engine = create_engine('postgresql://username:password@host:port/database_name')

Die Daten in eine Tabelle namens 'transactions' einfügen

df.to_sql('transactions', engine, if_exists='append', index=False)


In diesem Beispiel werden die Daten in eine Tabelle namens 'transactions' eingefügt.

## Auswahl der Einfügemethode

Der `if_exists`-Parameter in der `to_sql()`-Methode ermöglicht es Ihnen, anzugeben, wie mit dem Fall umgegangen werden soll, wenn die Tabelle bereits existiert. Hier sind die verfügbaren Optionen:

- `'fail'`: Ein `ValueError` wird ausgelöst, wenn die Tabelle bereits existiert.
- `'replace'`: Die Tabelle wird gelöscht, bevor die neuen Daten eingefügt werden.
- `'append'`: Neue Daten werden in die vorhandene Tabelle eingefügt.

Hier ist ein Beispiel für die Verwendung der Option `'replace'`:

```python
import pandas as pd
from sqlalchemy import create_engine

# Die Daten in ein pandas DataFrame laden
df = pd.read_csv('data.csv')

# Die Datenbank-Engine erstellen
engine = create_engine('postgresql://username:password@host:port/database_name')

# Die Daten einfügen und dabei die vorhandene Tabelle ersetzen
df.to_sql('transactions', engine, if_exists='replace', index=False)

In diesem Beispiel wird, wenn die Tabelle 'transactions' bereits existiert, diese gelöscht und mit den neuen Daten ersetzt.

Verständnis der Append- und Replace-Modi

Die Modi 'append' und 'replace' in der to_sql()-Methode haben unterschiedliche Auswirkungen auf Ihre Daten und die Tabellenstruktur.

  • 'append': In diesem Modus werden die neuen Daten zur vorhandenen Tabelle hinzugefügt und dabei die Tabellenstruktur und eventuell vorhandene Daten beibehalten.
  • 'replace': In diesem Modus wird die vorhandene Tabelle gelöscht und eine neue Tabelle mit den neuen Daten erstellt. Dies ist nützlich, wenn Sie den Inhalt der Tabelle vollständig ersetzen möchten, führt jedoch zum Verlust vorhandener Daten.

Die Wahl zwischen 'append' und 'replace' hängt von Ihrem spezifischen Anwendungsfall und den Anforderungen Ihrer Anwendung ab.

Optimierung der Leistung

Stapelweise Einfügungen

Das Einfügen von Daten stapelweise kann die Leistung des Einfügevorgangs erheblich verbessern. Hier ist ein Beispiel, wie Sie stapelweise Einfügungen mit pandas und sqlalchemy verwenden können:

import pandas as pd
from sqlalchemy import create_engine
 
# Die Daten in ein pandas DataFrame laden
df = pd.read_csv('data.csv')
 
# Die Datenbank-Engine erstellen
engine = create_engine('postgresql://username:password@host:port/database_name')
 
# Die Stapelgröße festlegen
batch_size = 10000
 
# Die Daten stapelweise einfügen
for i in range(0, len(df), batch_size):
    df.iloc[i:i+batch_size].to_sql('table_name', engine, if_exists='append', index=False)

In diesem Beispiel werden die Daten in Stapeln von jeweils 10.000 Zeilen auf einmal eingefügt, was die Gesamtleistung des Einfügevorgangs signifikant verbessern kann.

Parallele Verarbeitung nutzen

Sie können den Einfügevorgang weiter optimieren, indem Sie die parallele Verarbeitung nutzen. Hier ist ein Beispiel mit dem concurrent.futures-Modul:

import pandas as pd
from sqlalchemy import create_engine
from concurrent.futures import ThreadPoolExecutor
 
# Die Daten in ein pandas DataFrame laden
df = pd.read_csv('data.csv')
 
# Die Datenbank-Engine erstellen
engine = create_engine('postgresql://username:password@host:port/database_name')
 
# Die Stapelgröße und die Anzahl der Threads festlegen
batch_size = 10000
num_threads = 4
 
# Die Einfügefunktion definieren
def insert_batch(start_idx):
    df.iloc[start_idx:start_idx+batch_size].to_sql('table_name', engine, if_exists='append', index=False)
 
# ThreadPoolExecutor verwenden, um Daten parallel einzufügen
with ThreadPoolExecutor(max_workers=num_threads) as executor:
    futures = [executor.submit(insert_batch, i) for i in range(0, len(df), batch_size)]
    [future.result() for future in futures]

In diesem Beispiel verwenden wir einen ThreadPoolExecutor, um den Einfügevorgang über 4 Threads parallel auszuführen. Dies kann die Gesamtleistung des Einfügevorgangs erheblich verbessern, insbesondere bei großen Datensätzen.

Reduzierung des Speicherbedarfs

Bei der Arbeit mit großen Datensätzen ist es wichtig, den Speicherbedarf des Einfügevorgangs zu optimieren. Eine Möglichkeit dies zu tun ist die Verwendung des chunksize-Parameters in der to_sql()-Methode. Hier ist ein Beispiel:

import pandas as pd
from sqlalchemy import create_engine
 
# Die Datenbank-Engine erstellen
engine = create_engine('postgresql://username:password@host:port/database_name')
 
# Die Chunkgröße festlegen
chunksize = 100000
 
# Die Daten in Einzelteilen einfügen
for chunk in pd.read_csv('data.csv', chunksize=chunksize):
    chunk.to_sql('table_name', engine, if_exists='append', index=False)

In diesem Beispiel lesen wir die Daten in Teilen von jeweils 100.000 Zeilen und fügen sie in die Datenbank ein. Dies kann den Speicherbedarf des Einfügevorgangs reduzieren und ihn effizienter für große Datensätze machen.

Umgang mit Fehlern und Ausnahmen

Abfangen von datenbankbezogenen Fehlern

Beim Einfügen von Daten in eine Datenbank ist es wichtig, eventuelle Fehler zu behandeln. Hier ist ein Beispiel, wie man datenbankbezogene Fehler mit der sqlalchemy-Bibliothek abfangen kann:

import pandas as pd
from sqlalchemy import create_engine
from sqlalchemy.exc import SQLAlchemyError
 
# Die Datenbank-Engine erstellen
engine = create_engine('postgresql://username:password@host:port/database_name')
 
# Die Daten in ein pandas DataFrame laden
df = pd.read_csv('data.csv')
 
try:
    # Die Daten in die Datenbank einfügen
    df.to_sql('table_name', engine, if_exists='append', index=False)
except SQLAlchemyError as e:
    # Den Fehler behandeln
    print(f"Fehler beim Einfügen der Daten: {e}")

In diesem Beispiel fangen wir mögliche SQLAlchemyError-Ausnahmen ab, die während des Einfügevorgangs auftreten können, und behandeln sie entsprechend.

Protokollierung und Fehlersuche

Das Protokollieren kann ein wertvolles Werkzeug sein, um Probleme zu debuggen, die während des Daten-Einfügeprozesses auftreten können. Hier ist ein Beispiel dafür, wie man mit dem integrierten logging-Modul eine Protokollierung einrichtet:

import logging
import pandas as pd
from sqlalchemy import create_engine
from sqlalchemy.exc import SQL
 
## Bedingte Anweisungen
 
Bedingte Anweisungen in Python ermöglichen es Ihnen, verschiedene Codeblöcke basierend auf bestimmten Bedingungen auszuführen. Die häufigste bedingte Anweisung ist die `if-elif-else`-Anweisung.
 
```python
x = 10
if x > 0:
    print("x ist positiv")
elif x < 0:
    print("x ist negativ")
else:
    print("x ist null")

In diesem Beispiel wird der Codeblock unter der if-Anweisung ausgeführt, wenn x größer als 0 ist. Wenn x kleiner als 0 ist, wird der Codeblock unter der elif-Anweisung ausgeführt. Wenn keine dieser Bedingungen wahr ist, wird der Codeblock unter der else-Anweisung ausgeführt.

Sie können auch die and, or und not Operatoren verwenden, um mehrere Bedingungen zu kombinieren:

age = 25
if age >= 18 and age < 65:
    print("Sie sind erwachsen")
else:
    print("Sie sind nicht erwachsen")

In diesem Beispiel wird der Codeblock unter der if-Anweisung nur dann ausgeführt, wenn das Alter der Person größer oder gleich 18 und kleiner als 65 ist.

Schleifen

Schleifen in Python ermöglichen es Ihnen, einen Codeblock mehrmals auszuführen. Die beiden häufigsten Arten von Schleifen sind die for-Schleife und die while-Schleife.

Die for-Schleife wird verwendet, um über eine Sequenz zu iterieren (wie eine Liste, ein Tupel oder ein String):

fruits = ["apple", "banana", "cherry"]
for fruit in fruits:
    print(fruit)

In diesem Beispiel wird der Codeblock unter der for-Schleife für jedes Element in der fruits-Liste einmal ausgeführt.

Die while-Schleife wird verwendet, um einen Codeblock auszuführen, solange eine bestimmte Bedingung wahr ist:

count = 0
while count < 5:
    print(count)
    count += 1

In diesem Beispiel wird der Codeblock unter der while-Schleife solange ausgeführt, wie der Wert von count kleiner als 5 ist.

Sie können auch die break- und continue-Anweisungen verwenden, um den Ablauf einer Schleife zu steuern:

for i in range(10):
    if i == 5:
        break
    print(i)

In diesem Beispiel wird die Schleife abgebrochen, sobald der Wert von i gleich 5 ist.

for i in range(10):
    if i % 2 == 0:
        continue
    print(i)

In diesem Beispiel wird der Codeblock unter der for-Schleife nur für ungerade Zahlen ausgeführt, da die continue-Anweisung die geraden Zahlen überspringt.

Funktionen

Funktionen in Python sind Blöcke von wiederverwendbarem Code, die eine bestimmte Aufgabe ausführen. Sie können eine Funktion mit dem def-Schlüsselwort definieren, und Sie können die Funktion mit ihrem Namen aufrufen.

def greet(name):
    print(f"Hallo, {name}!")
 
greet("Alice")
greet("Bob")

In diesem Beispiel nimmt die greet()-Funktion ein einzelnes Argument name und druckt eine Begrüßungsnachricht mit diesem Namen aus. Die Funktion wird zweimal mit unterschiedlichen Argumenten aufgerufen.

Sie können auch Funktionen definieren, die Werte zurückgeben:

def add(a, b):
    return a + b
 
result = add(3, 4)
print(result)  # Ausgabe: 7

In diesem Beispiel nimmt die add()-Funktion zwei Argumente a und b und gibt ihre Summe zurück. Die Funktion wird aufgerufen und das Ergebnis wird in der Variablen result gespeichert.

Funktionen können auch Standardargumente und Argumente variabler Länge haben:

def print_info(name, age=30, *args):
    print(f"Name: {name}")
    print(f"Alter: {age}")
    print("Zusätzliche Informationen:")
    for arg in args:
        print(arg)
 
print_info("Alice", 25, "Lebt in New York", "Liebt Katzen")
print_info("Bob", hobbies="lesen", occupation="Software-Ingenieur")

In diesem Beispiel hat die print_info()-Funktion ein Standardargument age mit einem Wert von 30 und akzeptiert auch eine variable Anzahl zusätzlicher Argumente mit der *args-Syntax. Die Funktion wird zweimal mit unterschiedlichen Argumenten aufgerufen.

Module und Pakete

In Python können Sie Ihren Code in Module und Pakete organisieren, um ihn besser zu verwalten und wiederverwendbar zu machen.

Ein Modul ist eine Datei mit Python-Definitionen und -Anweisungen. Sie können ein Modul mithilfe der import-Anweisung importieren:

import math
print(math.pi)

In diesem Beispiel wird das math-Modul importiert und der Wert von pi mithilfe der Punktnotation zugegriffen.

Sie können auch bestimmte Funktionen oder Variablen aus einem Modul importieren:

from math import sqrt, pi
print(sqrt(16))
print(pi)

In diesem Beispiel werden die sqrt()-Funktion und die pi-Variable direkt aus dem math-Modul importiert.

Pakete sind Sammlungen von Modulen, die in Verzeichnissen organisiert sind. Sie können Ihre eigenen Pakete erstellen, indem Sie ein Verzeichnis erstellen und Ihre Moduldateien darin platzieren. Dann können Sie die Module aus dem Paket mithilfe der Punktnotation importieren:

import my_package.my_module
my_package.my_module.my_function()

In diesem Beispiel wird die my_function()-Funktion aus dem my_module-Modul importiert, das Teil des my_package-Pakets ist.

Datei-E/A

Python stellt integrierte Funktionen zum Lesen von Dateien und zum Schreiben in Dateien bereit. Die open()-Funktion wird verwendet, um eine Datei zu öffnen, und die close()-Funktion wird verwendet, um die Datei zu schließen.

file = open("example.txt", "w")
file.write("Hallo, Welt!")
file.close()

In diesem Beispiel wird eine neue Datei mit dem Namen example.txt im Schreibmodus ("w") geöffnet, und der String "Hallo, Welt!" wird in die Datei geschrieben. Schließlich wird die Datei geschlossen.

Sie können auch die with-Anweisung verwenden, um die Datei automatisch zu schließen, wenn Sie damit fertig sind:

with open("example.txt", "r") as file:
    content = file.read()
    print(content)

In diesem Beispiel wird die Datei im Lesemodus ("r") geöffnet, und der Inhalt der Datei wird gelesen und gedruckt.

Fehlerbehandlung

Python bietet eine Möglichkeit, Fehler und unerwartete Situationen mit der Fehlerbehandlung zu behandeln. Sie können die try-except-Anweisung verwenden, um Ausnahmen abzufangen und zu behandeln.

try:
    result = 10 / 0
except ZeroDivisionError:
print("Fehler: Division durch Null")

In diesem Beispiel versucht der Code im try-Block, 10 durch 0 zu teilen, was einen ZeroDivisionError auslöst. Der except-Block fängt diesen Fehler ab und gibt eine Fehlermeldung aus.

Sie können auch mehrere Ausnahmen behandeln und einen Standard-except-Block bereitstellen:

try:
    x = int(input("Geben Sie eine Zahl ein: "))
    print(10 / x)
except ValueError:
    print("Fehler: Ungültige Eingabe")
except ZeroDivisionError:
    print("Fehler: Division durch Null")
else:
    print("Erfolg!")
finally:
    print("Ausführung abgeschlossen")

In diesem Beispiel versucht der Code im try-Block, die Eingabe des Benutzers in eine Ganzzahl zu konvertieren und anschließend 10 durch das Ergebnis zu teilen. Wenn der Benutzer einen nicht-numerischen Wert eingibt, wird ein ValueError ausgelöst und der entsprechende except-Block wird ausgeführt. Wenn der Benutzer 0 eingibt, wird ein ZeroDivisionError ausgelöst und der entsprechende except-Block wird ausgeführt. Wenn keine Ausnahmen auftreten, wird der else-Block ausgeführt. Der finally-Block wird immer ausgeführt, unabhängig davon, ob eine Ausnahme aufgetreten ist oder nicht.

Fazit

In diesem Python-Tutorial haben Sie verschiedene Themen kennengelernt, darunter bedingte Anweisungen, Schleifen, Funktionen, Module und Pakete, Datei-E/A und die Behandlung von Ausnahmen. Diese Konzepte sind entscheidend für den Aufbau robuster und effizienter Python-Anwendungen. Denken Sie daran, mit den bereitgestellten Codebeispielen zu üben und zu experimentieren, um Ihr Verständnis dieser Konzepte zu festigen. Viel Glück bei Ihrer Python-Programmierreise!

MoeNagy Dev