Photo by James Harrison on Unsplash
… e tu perdi ore a capire perché diamine le cose non funzionano!! 😡
Sto sviluppando una applicazione che permette di generare database di persone inventate sfruttando il modulo Faker
Sfortunatamente sono incappato nel modulo sqlite3
di Python. Sfortunatamente, perché, gli sviluppatori di questo modulo hanno lavorato un po' in modo pedestre. Almeno per quanto riguarda la funzione sqlite3.connect()
. Nel mio sorgente la prima cosa che chiedo è se l’utente preferisca usare un database MySQL oppure SQLite e, di conseguenza, controllo in entrami i casi se i database esistano o meno, nel secondo caso, ovviamente, la prima cosa che faccio è creare il database con la relativa tabella che mi servirà. Per MySQL non ho trovato problemi di sorta: con questa funzione faccio il controllo e verifico che esista il database:
import pymysql
def check_if_MySqlDB_exist(host, user, password, db_name, tbl_name, error_db, error_tbl):
conn = pymysql.connect(host=host, user=user, password=password)
cursor = conn.cursor()
cursor.execute("SHOW DATABASES")
databases = cursor.fetchall()
for database in databases:
if db_name in database:
cursor.execute(f"use {db_name}")
cursor.execute("show tables;")
tables = cursor.fetchall()
for table in tables:
if tbl_name in table[0]:
return True
print(error_tbl)
return False
print(error_db)
return False
E fin qui nessun problema. Il problema è sorto quando ho affrontato la questione file sqlite3
: chiedo all’utente il nome del file e verifico:
1. Che esista. 2. Che sia un database. Con questa semplice funzione credevo di aver risolto il problema:
import sqlite3
try:
connection = sqlite3.connect(FileName)
except sqlite3.DatabaseError:
return False
return true
Ed invece no: aprendo un file, che non sia un file sqlite
, non riceverete come ci aspetterebbe che ritorni False! L’api sqlite3.connect()
apre solo il file SENZA alcun test di coerenza del contenuto!! Quindi che apriate un database sqlite3
o un file della ricetta della nonna, dei biscotti, non genererà alcun trap attraverso il try:
!!! Il modo più sicuro che ho trovato per testare che sia davvero un file database di sqlite3
è il seguente:
def check_if_is_SQLite_DB(DbFileName: str):
with open(DbFileName,’r’, encoding = "UTF-8") as f:
header = f.read(16)
if header.startswith(‘SQLite format 3’):
return True
else:
return False
Ci ho perso delle ore a capire perché diamine la funzione fallisse il test!!!! Praticamente sqlite3.connect()
non fa altro che controllare che il file sia lì, e si possa aprire, STOP. Che poi sia davvero un file di database specifico di sqlite3
non è un problema che pare debba interessare alla funzione! Io davvero sono rimasto bastito ad aver dovuto perdere tempo per una cosa del genere; peraltro per curiosità sono andato a cercare informazioni a riguardo, sul sito del modulo di sqlite3, ed esattamente qui tutto dicono della sqlite3.connect()
tranne che non verifichi che sia realmente un database sqlite3
! Quindi, se vi capita di dover manipolare un database sqlite[3]
tenete a mente questa cosa, se pensate di verificare che il file che aprirete sia davvero un file di quella tipologia, perché la sqlite3.connect()
non se ne preoccupa proprio!
J.C.