Sie haben Recht, das .import
ist der richtige Weg, aber das ist ein Befehl aus der SQLite3.exe-Shell. Viele der häufigsten Antworten auf diese Frage betreffen native Python-Schleifen. Wenn Ihre Dateien jedoch groß sind (meine sind 10 ^ 6 bis 10 ^ 7 Datensätze), möchten Sie vermeiden, alles in Pandas einzulesen oder ein natives Python-Listenverständnis / eine native Python-Listenschleife zu verwenden (obwohl ich sie nicht zum Vergleich zeitlich festgelegt habe).
Für große Dateien ist es meiner Meinung nach die beste Option, die leere Tabelle im Voraus zu erstellen sqlite3.execute("CREATE TABLE...")
, die Header aus Ihren CSV-Dateien subprocess.run()
zu entfernen und dann die Importanweisung von sqlite auszuführen. Da der letzte Teil meiner Meinung nach der relevanteste ist, werde ich damit beginnen.
subprocess.run()
from pathlib import Path
db_name = Path('my.db').resolve()
csv_file = Path('file.csv').resolve()
result = subprocess.run(['sqlite3',
str(db_name),
'-cmd',
'.mode csv',
'.import '+str(csv_file).replace('\\','\\\\')
+' <table_name>'],
capture_output=True)
Erläuterung
In der Befehlszeile suchen Sie nach dem Befehl sqlite3 my.db -cmd ".mode csv" ".import file.csv table"
. subprocess.run()
führt einen Befehlszeilenprozess aus. Das Argument to subprocess.run()
ist eine Folge von Zeichenfolgen, die als Befehl interpretiert werden, gefolgt von allen Argumenten.
sqlite3 my.db
öffnet die Datenbank
-cmd
Mit flag nach der Datenbank können Sie mehrere Folgebefehle an das SQLite-Programm übergeben. In der Shell muss jeder Befehl in Anführungszeichen stehen, aber hier müssen sie nur ihr eigenes Element der Sequenz sein
'.mode csv'
tut, was Sie erwarten würden
'.import '+str(csv_file).replace('\\','\\\\')+' <table_name>'
ist der Importbefehl.
Da der Unterprozess alle Folgemaßnahmen -cmd
als Zeichenfolgen in Anführungszeichen übergibt , müssen Sie Ihre Backslashes leider verdoppeln, wenn Sie einen Windows-Verzeichnispfad haben.
Header entfernen
Nicht wirklich der Hauptpunkt der Frage, aber hier ist, was ich verwendet habe. Auch hier wollte ich zu keinem Zeitpunkt die gesamten Dateien in den Speicher lesen:
with open(csv, "r") as source:
source.readline()
with open(str(csv)+"_nohead", "w") as target:
shutil.copyfileobj(source, target)