csv iin MySQL schreiben

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.
Antworten
KDennsOD
User
Beiträge: 1
Registriert: Freitag 3. Juli 2020, 13:25

Moin,

ich möchte gern ein csv file in eine MySQL Datenbank importieren. Das Problem ist hier anscheinend das Format des csv files.
Das csv file sieht so aus:

"item_id, timestamp, demand, location"
"311,2020-06-22 00:00:00,1,30421"
"1105,2020-06-22 00:00:00,1,01668"

Mit diesem Python Code versuche ich die Datei einzulesen und in die DB zu schreiben. Leider bekomme ich die double quotes nicht weg und egal was ich tue, entweder eine Zeile wird als ein String erkannt oder er gibt mir Unsinn aus. Kann mir jemand helfen?

Code: Alles auswählen

from __future__ import print_function
import boto3
import logging
import os
import sys
import uuid
import pymysql
import csv
import rds_config


rds_host  = rds_config.rds_host
name = rds_config.db_username
password = rds_config.db_password
db_name = rds_config.db_name


logger = logging.getLogger()
logger.setLevel(logging.INFO)

try:
    conn = pymysql.connect(rds_host, user=name, passwd=password, db=db_name, connect_timeout=5)
except Exception as e:
    logger.error("ERROR: Unexpected error: Could not connect to MySql instance.")
    logger.error(e)
    sys.exit()
    
logger.info("SUCCESS: Connection to RDS mysql instance succeeded")


#def s3_client():
    
#    s3 = boto3.client('s3')
#    return s3
s3_client = boto3.client('s3')

def lambda_handler(event, context):

    bucket = event['Records'][0]['s3']['bucket']['name']
    key = event['Records'][0]['s3']['object']['key'] 
    download_path = '/tmp/{}{}'.format(uuid.uuid4(), key)

    s3_client.download_file(bucket, key,download_path)

    csv_data = csv.reader(open( download_path), delimiter = ',', quotechar='\"', quoting=csv.QUOTE_MINIMAL)

    with conn.cursor() as cur:
        for idx, row in enumerate(reader):

            logger.info(row)
            try:
                cur.execute('INSERT INTO forecast_data(item_id, timestamp, demand, location)' \
                                'VALUES("%s", "%s", "%s", "%s")'
                                , row)
            except Exception as e:
                logger.error(e)

            if idx % 100 == 0:
                conn.commit()

        conn.commit()

    return 'File loaded into RDS:' + str(download_path)
Sirius3
User
Beiträge: 18272
Registriert: Sonntag 21. Oktober 2012, 17:20

Du hast doppelt verpackte CSV-Daten. Das ist natürlich ziemlich blöd, weil Du einen csv-Reader in einen csv-Reader packen mußt.
Der except-Block ist unnötig, da er einen Lesbaren Traceback in eine schwierig lesbare Fehlermeldung verwandelt.
Die Platzhalter beim execute sind falsch. Die müssen ohne Anführungszeichen im SQL-Statement stehen.
Auch hier ist die Fehlerbehandlung quatsch und kann weg.
Benutzeravatar
__blackjack__
User
Beiträge: 14052
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@KDennsOD: Zusätzlich zu dem was Sirius3 geschrieben hat: Dateien die man öffnet, sollte man auch wieder schliessen. Wo es möglich ist, sollte man dazu die ``with``-Anweisung verwenden.

CSV-Dateien brauchen das Argument ``newline=""`` beim öffnen.

Die Daten werden gar nicht umgewandelt nach dem einlesen‽ Es kann sein, dass MySQL das auch so schluckt, das wäre dann aber eher Zufall.

Du übergibst im Grund die Defaultwerte an `csv.reader()`.

Wenn Du ausnahmen protokollieren willst, dann besser mit `logger.exception()`, denn dann hast Du am Ende auch den Traceback.

Das `sys.exit()` wäre überflüssig wenn Du ``else`` verwenden würdest. Wenn man `sys.exit()` aufruft, sollte man mindestens potentiell einen anderen Rückgabewert als 0 an den Aufrufer liefern, sonst ist diese Funktion in 99,9% der Fälle eine Abkürzung um den Programmfluss nicht ordentlich strukturieren zu müssen.

Der `__future__`-Import ist in Python 3 nicht mehr nötig. Und Du verwendest ja sicher kein Python mehr das nicht mehr supported wird‽
“Vir, intelligence has nothing to do with politics!” — Londo Mollari
Antworten