Masz rację, .import
to jest właściwy sposób, ale to polecenie z powłoki SQLite3.exe. Wiele najpopularniejszych odpowiedzi na to pytanie dotyczy natywnych pętli Pythona, ale jeśli twoje pliki są duże (moje to 10 ^ 6 do 10 ^ 7 rekordów), nie chcesz czytać wszystkiego w pandach lub używać natywnego rozumienia / pętli list Pythona (chociaż nie czas na ich porównanie).
W przypadku dużych plików uważam, że najlepszą opcją jest wcześniejsze utworzenie pustej tabeli za pomocą sqlite3.execute("CREATE TABLE...")
, usunięcie nagłówków z plików CSV, a następnie użycie subprocess.run()
do wykonania instrukcji importu sqlite. Ponieważ ostatnia część jest, moim zdaniem, najbardziej trafna, zacznę od tego.
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)
Wyjaśnienie
W wierszu poleceń szukane polecenie to sqlite3 my.db -cmd ".mode csv" ".import file.csv table"
. subprocess.run()
uruchamia proces wiersza poleceń. Argument do subprocess.run()
jest sekwencją ciągów, które są interpretowane jako polecenie, po którym następują wszystkie jego argumenty.
sqlite3 my.db
otwiera bazę danych
-cmd
Flaga po bazie danych pozwala na przekazywanie wielu poleceń do programu sqlite. W powłoce każde polecenie musi być w cudzysłowach, ale tutaj wystarczy, że będzie to ich własny element sekwencji
'.mode csv'
robi to, czego można się spodziewać
'.import '+str(csv_file).replace('\\','\\\\')+' <table_name>'
to polecenie importu.
Niestety, ponieważ podproces przekazuje wszystkie następstwa -cmd
jako łańcuchy cytowane w cudzysłowie, musisz podwoić ukośniki odwrotne, jeśli masz ścieżkę do katalogu systemu Windows.
Usuwanie nagłówków
Właściwie nie jest to główny punkt pytania, ale oto, czego użyłem. Ponownie, w żadnym momencie nie chciałem wczytywać całych plików do pamięci:
with open(csv, "r") as source:
source.readline()
with open(str(csv)+"_nohead", "w") as target:
shutil.copyfileobj(source, target)