|
Avanti
Indietro
Indice
MySQLdb avvolge
_mysql
rendendolo compatibile con
l'interfaccia API Python per i DB (versione 2). In realtà una piccola
parte del codice che implementa l'API si trova in _mysql per ragioni
di efficienza.
Le
Specifiche dell'API DB 2.0 dovrebbero costituire la guida principale nell'uso di questo
modulo. Verrà qui documentato solo quanto si scosta da tali specifiche e
altre faccende strettamente dipendenti dal database.
Solo poche funzioni e attributi al livello più alto sono definiti
all'interno di MySQLdb.
-
connect(parametri...)
Il costruttore per
creare una connessione al database. Restituisce un Oggetto Connessione.
I parametri sono gli stessi dell'API C MySQL. In aggiunta, ci sono alcune
parole chiave addizionali che corrispondono a quanto si passerebbe a
mysql_options() prima di connettersi. Si noti che alcuni parametri
devono essere specificati come argomenti a parole chiave! Il valore
predefinito per ciascun parametro è NULL o zero, come appropriato.
Si consulti la documentazione MySQL per maggiori dettagli. I parametri
importanti sono:
- host
nome dell'host a cui connettersi. Default: usa localhost
- user
utente con il quale autenticarsi. Default: l'utente attuale.
- passwd
password con la quale autenticarsi. Default: nessuna password.
- db
database da usare. Default: nessun database.
- port
Porta TCP del server MySQL. Default: la sua porta standard (3306).
- unix_socket
collocazione del socket UNIX. Default: usa TCP.
- conv
dizionario di conversione dei tipi.
Default: una copia di MySQLdb.converters.conversions
- compress
abilita il protocollo di compressione. Default:
nessuna compressione.
- connect_timeout
fallisce se la connessione non è
completata entro un dato numero di secondi. Default: nessun
timeout (?)
- named_pipe
usa una pipe con nome (Windows). Default: non
usarla.
- init_command
comando iniziale da inviare al server subito
dopo la connessione. Default: nessuno.
- read_default_file
file di configurazione MySQL da leggere; si
veda la documentazione MySQL per mysql_options() .
- read_default_group
gruppo di default con cui leggere il file
di configurazione; si veda la documentazione MySQL per
mysql_options() .
- cursorclass
classe cursore usata da cursor() , a meno di
sovrascritture. Default: MySQLdb.cursors.Cursor .
Questo dev'essere un parametro a parola chiave.
- apilevel
costante stringa che specifica il livello dell'API DB supportato. È
pari a '2.0'.
- threadsafety
costante intera che specifica il livello di supporto ai
thread dell'interfaccia. Per MySQLdb versione 0.9.0 è pari a 1, che
significa: i thread possono condividere il modulo.
Il protocollo MySQL non può gestire più thread usando una
stessa connessione in modo immediato. Alcune versioni precedenti di MySQLdb
utilizzavano i lock per raggiungere un livello di supporto ai thread pari a
2. Non è cosa difficile da realizzare con la classe Cursore standard
(che usa mysql_store_result() ), è invece complicato per SSCursor
(che usa mysql_use_result() ). Nel secondo caso ci si deve assicurare
che tutte le righe siano state lette prima che possa essere eseguita un'altra
interrogazione. Le cose si complicano ulteriormente con l'aggiunta delle
transazioni, dato che queste iniziano quando un cursore esegue
un'interrogazione ma finiscono quando l'oggetto Connessione esegue un
COMMIT o un ROLLBACK . Due thread non possono condividere una
connessione mentre una transazione è in corso, oltre a non essere in
grado di condividerla durante l'esecuzione di un'interrogazione. Tutto questo
comporta una complicazione eccessiva a livello del codice, al punto che non
ne vale proprio la pena.
La conclusione generale è: meglio non condividere connessioni
fra thread. Dato lo sforzo necessario non vale la pena e alla fine si
rischia anche di compromettere le prestazioni del programma, dato che il
server MySQL lancia un thread separato per ciascuna connessione. Si possono
certamente fare cose come tenere un pool delle connessioni e passarle a un
thread in una volta sola. Se invece si permette a due thread di usare
simultaneamente una stessa connessione, con tutta probabilità la
libreria client MySQL farà una brutta fine. L'avviso l'ho dato.
- paramstyle
costante stringa che specifica il tipo di formattazione
del marcatore di parametro che l'interfaccia si aspetta. Impostato a 'format'
usa i codici di formato della printf di ANSI C, p.e. '...WHERE name=%s'.
Se a conn.execute() viene passato un dizionario, allora l'interfaccia
userà in realtà 'pyformat', cioè i codici di formato
Python estesi, p.e. '...WHERE name=%(name)s'. In ogni caso l'API attualmente
non permette di specificare più di uno stile.
Nota di compatibilità: il vecchio MySQLmodule usa uno schema simile, ma
richiede che le stringhe di formato che contengono stringhe, date e altri
dati carattere simili siano circondate da virgolette. Questo non è
necessario per MySQLdb. Si raccomanda di usare %s (e non '%s') per tutti i
parametri, di qualunque tipo siano. L'interfaccia aggiungerà tutte le
virgolette necessarie.
-
conv
un dizionario che mappa i tipi MySQL (da
FIELD_TYPE.* ) in oggetti invocabili Python (di solito funzioni),
che si occupano della conversione da stringa al tipo desiderato, e i tipi
Python in oggetti invocabili Python, che effettuano la conversione opposta
in stringhe letterali SQL. Il dizionario viene inizializzato con contenuti
predefiniti appropriati per la gran parte dei tipi. Quando si crea un oggetto
Connessione, è possibile passare il proprio dizionario di conversione
come parametro a parola chiave. Altrimenti verrà usata una copia di
MySQLdb.converters.conversions . Il dizionario include alcune delle
funzioni fabbrica del modulo DateTime , se esso risulta disponibile.
Parecchi tipi non standard sono restituiti come stringhe, che è il
modo in cui MySQL restituisce tutte le colonne. Per maggiori dettagli si veda
la documentazione incorporata nel modulo.
A partire da MySQL-3.23, MySQL supporta set differenti di caratteri nel server
e una nuova funzione di protezione per le stringhe nelle interrogazioni SQL,
mysql_real_escape_string() . Questo richiede che la funzione sia un metodo
associato a un oggetto Connessione. MySQLdb gestisce tutto ciò
automaticamente. Nondimeno se si pensa di aver bisogno di fare qualcosa di
strambo con le proprie stringhe, si potrà modificare il dizionario una
volta aperta la connessione. In pratica non ci si dovrà mai preoccupare
di tutto questo.
Gli oggetti Connessione sono il prodotto della funzione connect() .
- commit()
se il database e le tabelle supportano le transazioni
questo metodo effettua il commit della transazione corrente, altrimenti
non fa nulla [senza creare problemi ma nemmeno avvisare NdT].
-
rollback()
se il database e le tabelle
supportano le transazioni questo metodo fa il "roll back", in parole povere
annulla, la transazione corrente, altrimenti viene sollevata un'eccezione
NotSupportedError .
Nota di compatibilità: nel vecchio
MySQLmodule
questo metodo
invece di sollevare un'eccezione in caso le transazioni non siano
supportate non fa proprio nulla, portando a credere che il rollback
abbia avuto successo. Questo è un comportamento pericoloso, dato
che un rollback riuscito indica che la transazione corrente è
stata ritirata, il che non è vero, e fallisce nel comunicare al
programmatore che ora il database dev'essere ripulito in altri modi.
- cursor([cursorclass])
MySQL non supporta nativamente i cursori.
Ad ogni modo essi possono venir facilmente emulati. Si può
fornire una classe cursore alternativa come parametro opzionale.
In caso non sia presente, viene preso come default il valore passato
al momento della creazione dell'oggetto Connessione, o la classe
standard Cursor . Si vedano anche le classi cursori aggiuntive
nella sezione Usare ed estendere il modulo.
- begin()
inizia in modo esplicito una transazione. Normalmente
non è necessario usarlo: l'esecuzione di un'interrogazione
inizia in modo implicito una nuova transazione se non ce ne sono
altre in corso. Se è attivato il modo AUTOCOMMIT, si può
usare begin() per disattivarlo temporaneamente. AUTOCOMMIT si
riattiverà alla prossimo commit() o rollback .
- callproc()
non implementato.
- close()
chiude il cursore. Da qui in poi se si tenteranno operazioni sul cursore
verrà sollevata un'eccezione ProgrammingError . Se si stanno
usando i
cursori lato server ["Server-Side
Cursors"], è molto importante chiudere il cursore quando si ha
finito di usarlo e prima di crearne uno nuovo.
- insert_id()
restituisce l'ultimo valore AUTO_INCREMENT
inserito nel database. (Non-standard)
- info()
restituisce alcune informazioni sull'ultima interrogazione. Di
norma non serve. Con il cursore predefinito, qualsiasi avviso emesso da
MySQL causerà un'eccezione Warning . Se invece si sta usando
una classe cursore senza avvisi, allora si potrebbe volerlo usare. Si
veda la documentazione MySQL per mysql_info() . (Non-standard)
- setinputsizes()
non fa nulla, senza avvisare.
- setoutputsizes()
non fa nulla, senza avvisare.
Il metodo connect() lavora all'incirca come con _mysql :
import MySQLdb
db=MySQLdb.connect(passwd="moonpie",db="thangs")
Per effettuare un'interrogazione serve innanzitutto un cursore, sul quale poi
si andranno a eseguire le interrogazioni.
c=db.cursor()
max_price=5
c.execute("""SELECT spam, eggs, sausage FROM breakfast
WHERE price < %s""", (max_price,))
In questo esempio max_price=5 . Quindi perché usare %s nella
stringa? Perché MySQLdb la convertirà in un valore letterale
SQL, la stringa '5'. Una volta finito, l'interrogazione in realtà
reciterà: "...WHERE price < 5".
Perché la tupla? Perché la API DB richiede di passare come
sequenza qualsiasi parametro.
Ora ecco i risultati:
>>> c.fetchone()
(3L, 2L, 0L)
Diversamente da quanto accadeva con _mysql , il nostro esempio restituisce
una singola tupla, che sarebbe la riga, e i valori sono adeguatamente convertiti per
default... tranne... ma cosa sono le L?
Come detto in precedenza, mentre una colonna di MySQL di tipo INTEGER si traduce
perfettamente in un intero Python, un UNSIGNED INTEGER potrebbe causare overflow.
Tali valori sono quindi convertiti invece in interi long Python. Prima di Python
1.6, gli interi long conservavano la L quando convertiti in stringhe con
str() . Da 1.6 in poi str() non include più la L. Naturalmente
la L viene sempre stampata quando si usa repr() , il che è quanto
è successo nel nostro caso.
Quando si ha finito con una transazione, si dovrebbe eseguire db.commit()
o db.rollback() . Se il server e le tabelle non supportano le transazioni,
commit() funzionerà ancora, mentre rollback() solleverà
un'eccezione. Si noti che questi sono metodi di connection, non di
cursor, anche se è stato c.execute(...) a iniziare la
transazione.
Se si vogliono più righe si possono usare c.fetchmany(n) o
c.fetchall() . Questi due fanno esattamente quanto ci si aspetta. Per
c.fetchmany(n) , n è opzionale e il valore predefinito
è c.arraysize , che di norma è 100. Entrambi i metodi
restituiscono una sequenza di righe, o una sequenza vuota se le righe sono
finite. Se si usa una classe cursore personalizzata in modo particolare, le
righe stesse potrebbero non essere tuple.
Si noti che al contrario di quanto sopra, c.fetchone() restituisce None
quando non ci sono più righe da poter prelevare.
L'unico altro metodo che si userà quasi sicuramente serve negli inserimenti
multiriga:
c.execute("""INSERT INTO breakfast (name, spam, eggs, sausage, price)
VALUES (%s, %s, %s, %s, %s)""",
[ ("Spam and Sausage Lover's Plate", 5, 1, 8, 7.95 ),
("Not So Much Spam Plate", 3, 2, 0, 3.95 ),
("Don't Wany ANY SPAM! Plate", 0, 4, 3, 5.95 )
]
)
In questo esempio stiamo inserendo tre righe di cinque valori. Si noti che
c'è una mescolanza di tipi (stringhe, interi, numeri a virgola mobile)
ma stiamo ancora usando il solo %s . Si noti anche che abbiamo incluso
le stringhe di formato per una sola riga. MySQLdb le individua e le duplica per
ciascuna riga.
I fagioli al forno sono finiti!
Avanti
Indietro
Indice
| |