PROGRAMMAZIONE
Python
Docente: Armando Valentino
LINGUAGGIO Python
Database e Python
P ro f . A rm a n do Va le n t in o
SQLITE
SQLite è una libreria in linguaggio C che implementa un motore di database SQL relativamente veloce, serverless,
autonomo e altamente affidabile.
SQLite è il motore di database più comunemente utilizzato in ambiente di test
Python ha una libreria per accedere ai database SQLite, chiamata sqlite3.
SQLite ha le seguenti funzionalità: • Senza server SQLite non richiede un server per funzionare. Il database SQLite è unito
• Senza server all'applicazione che accede al database. Il database SQLite legge e
• Autonomo scrive direttamente dal database memorizzati sul disco e le applicazioni
• Configurazione zero interagiscono con quel database SQLite.
• Transazionale
• Database singolo
In genere, un RDBMS come MySQL, PostgreSQL, Oracle, ecc.,
necessita di un processo server separato per funzionare.
Le applicazioni che vogliono accedere al server del database
utilizzano il protocollo TCP/IP per inviare e ricevere richieste e
questa è chiamata architettura client/server.
P ro f . A rm a n do Va le n t in o 3
SQLITE
• Autonomo SQLite è autosufficiente, ovvero non necessita di dipendenze esterne come un sistema
operativo o una libreria esterna.
Questa caratteristica di SQLite è utile soprattutto nei dispositivi embedded come iPhone, telefoni
Android, console di gioco, lettori multimediali portatili, ecc.
• Configurazione zero Non richiede alcuna configurazione o amministrazione. Grazie all'architettura
serverless, non è necessario "installare" SQLite prima di utilizzarlo. Non c'è alcun
processo server che deve essere configurato, avviato e arrestato
• Transazionale SQLite è transazionale, ovvero è atomico, coerente, isolato e durevole (ACID). Tutte le
transazioni in SQLite sono completamente conformi ad ACID. In altre parole, tutte le
modifiche all'interno di una transazione avvengono completamente o per niente, anche
quando si verifica una situazione imprevista come un crash dell'applicazione,
un'interruzione di corrente o un crash del sistema operativo
• Database singolo SQLite è un singolo database, il che significa che consente a una singola connessione al
database di accedere a più file di database contemporaneamente
P ro f . A rm a n do Va le n t in o 4
Sistemi ACID
Sistemi ACID: Sono i database relazionali classici (come PostgreSQL, MySQL, Oracle, SQLite). Sono indispensabili per
sistemi finanziari, e-commerce, banche e ovunque l'errore sul dato non sia tollerabile.
L'acronimo ACID definisce le quattro proprietà fondamentali che un Database Relazionale (DBMS) deve garantire per
assicurare che le transazioni sui dati siano sicure, affidabili e prive di errori, anche in caso di guasti elettrici, crash del
sistema o accessi simultanei
1. Atomicity (Atomicità)
Concetto: Una transazione è un'unità indivisibile: o viene eseguita tutta o nulla.
2. Consistency (Consistenza)
Concetto: Una transazione porta il database da uno stato valido a un altro stato valido, rispettando tutte le regole e i
vincoli stabiliti (es. chiavi primarie, vincoli di unicità, saldi non negativi)
3. Isolation (Isolamento)
Concetto: Le transazioni eseguite contemporaneamente devono essere isolate l'una dall'altra. Il risultato finale deve
essere lo stesso come se le transazioni fossero state eseguite una dopo l'altra (in modo seriale).
4. Durability (Durabilità)
Concetto: Una volta che una transazione è conclusa con successo (commit), le modifiche apportate sono permanenti e
non verranno perse, nemmeno se subito dopo si verifica un blackout totale del server.
P ro f . A rm a n do Va le n t in o 5
SQLite in Python
Il modulo sqlite3 di Python fornisce un'interfaccia SQL che è stata progettata
per accedere al database
Utilizzo di sqlite
1. Connessione
sqliteConnection = [Link]('[Link]‘) #se non esiste lo crea
1. Creazione di un cursore della connessione
cursor = [Link]()
1. Scrittura query
query = SELECT * FROM TABELLA;'
1. Esecuzione query
[Link](query)
1. Recupero risultati
result = [Link]()
1. Stampa
print('SQLite Version is {}'.format(result))
P ro f . A rm a n do Va le n t in o 6
SQLITE
TIPI DI DATI E CORRISPONDENZA TRA SQLITE E PYTHON
SQLITE Python Datatype
NULL None
INTEGER int
REAL float
TEXT str
BLOB bytes
P ro f . A rm a n do Va le n t in o 7
Comandi SQL
1. CREATE (Inserimento)
L'operazione di creazione si esegue tramite il comando INSERT INTO. Serve a popolare le tabelle con nuovi record.
INSERT INTO Utenti (nome, cognome, email, data_iscrizione) VALUES ('Marco', 'Rossi', '[Link]@[Link]', '2024-03-08');
2. READ (Lettura)
L'operazione di lettura utilizza il comando SELECT. È il comando più versatile, poiché permette di filtrare, ordinare e aggregare i dati.
SELECT nome, email
FROM Utenti
WHERE cognome = 'Rossi';
3. UPDATE (Aggiornamento)
Per modificare dati esistenti si utilizza il comando UPDATE.
UPDATE Utenti
SET email = 'm.rossi_nuova@[Link]'
WHERE id_utente = 1;
4. DELETE (Cancellazione)
L'operazione di rimozione avviene tramite il comando DELETE. Anche in questo caso, la clausola WHERE è critica per evitare la perdita
totale dei dati.
DELETE FROM Utenti
WHERE id_utente = 1;
P ro f . A rm a n do Va le n t in o 8
ESERCIZIO
Creazione Database Prodotti # Inserimento prodotti (usiamo segnaposto per sicurezza)
prodotti = [
( "pane", 1.5, 5),
( "latte", 1.0, 10),
( "vino", 10.0, 5),
[Link]('''
( "carne", 1.5, 5),
CREATE TABLE IF NOT EXISTS prodotto ( ( "patate", 1.0, 10),
id INTEGER PRIMARY KEY AUTOINCREMENT, ( "mele", 10.0, 5),
nome TEXT NOT NULL, ( "marmellata", 1.5, 5),
prezzo REAL NOT NULL, ( "biscotti", 1.0, 10),
quantita INTEGER ( "carta igienica", 10.0, 5),
( "fazzoletti", 1.5, 5),
)
( "cicorie", 1.0, 10),
''') ( "prosciutto", 10.0, 5)
]
[Link]("INSERT INTO prodotto (nome, prezzo,
quantita) VALUES (?, ?, ?)", prodotti)
[Link]() # scrive sul disco
P ro f . A rm a n do Va le n t in o 9
SqlAlchemy
SQLAlchemy è l’ORM (Object-Relational
Mapper) più potente e diffuso per Python.
Facilita la comunicazione tra programmi
Python e il database ed è open source.
ORM è consente di rappresentare i record di un database
come oggetti corrispondenti nei linguaggi di
programmazione. Pertanto, è possibile interagire ed
eseguire operazioni su tali record di un database come se
si trattasse di oggetti.
L'ORM ci dà la possibilità di trasformare i record del
database in oggetti , rendendo le interazioni e le
modifiche del database semplici come la gestione degli
oggetti nei linguaggi di programmazione.
P ro f . A rm a n do Va le n t in o 10
SqlAlchemy
È formato da due layer principali
della libreria:
a) Core (orientato al linguaggio
SQL e agli schemi)
a) ORM (Object-Relational
Mapping, orientato agli oggetti
Python).
P ro f . A rm a n do Va le n t in o 11
SqlAlchemy: caratteristiche
• Astrazione dal database: Puoi lavorare con diversi tipi di database (Mysql, SQL Server,
PostgreSQ, ecc..), basta cambiare solo una riga (l'URL
dell'engine), spostando tutto su un altro database.
• Sicurezza: Protegge automaticamente dalle "SQL Injection" (attacchi
hacker tramite input di testo).
• Gestione degli oggetti: Quando recuperi un dato dal DB, SQLAlchemy ti restituisce
un oggetto Python su cui puoi chiamare metodi (non una
semplice lista di testi e numeri).
• Relazioni: Gestisce in modo automatico i legami tra tabelle tramite il
comando relationship.
P ro f . A rm a n do Va le n t in o 12
SqlAlchemy: vantaggi vs svantaggi
Vantaggi Svantaggi
Conciso. ORM consente agli utenti l’utilizzo del linguaggio con
una sintassi più concisa e semplice rispetto all'utilizzo di query Tempo. SqlAlchemy è un framework, e
SQL non elaborate, riducendo la quantità di codice necessaria. per usarlo bisogna sapere come
funziona dedicando del tempo
Ottimale. ORM consente inoltre agli utenti di sfruttare
l'ottimizzazione della programmazione orientata agli oggetti,
all‘utilizzo di questo strumento.
come ereditarietà, incapsulamento e astrazione, Minore controllo. Utilizzando
rappresentando i record del database come oggetti. SqlAlchemy si ha meno controllo
diretto su database perchè tutte le
Flessibile. Con ORM, gli utenti possono passare facilmente da operazioni sul DB sono svolte da
un sistema di gestione di database all'altro (MySQL, Sqlite3,
PostgreSQL, ecc.) senza dover possedere una conoscenza SqlAlchemy
approfondita di questi sistemi e del linguaggio SQL.
P ro f . A rm a n do Va le n t in o 13
SQLAlchemy
P ro f . A rm a n do Va le n t in o 14
Confronto tra mapper
Caratteristica Dichiarativo Imperativo
Forte (Classe e Tabella sono una Debole (Classe e Tabella sono
Accoppiamento
cosa sola) separate)
Più verbosa, richiede più
Leggibilità Alta, molto "Pythonic"
boilerplate (codice standard)
Gestita automaticamente dalla Gestita manualmente tramite il
Meta-programmazione
classe Base Registro
Standard per la maggior parte dei Ideale per sistemi legacy o
Flessibilità
progetti Domain Driven Design (DDD)
P ro f . A rm a n do Va le n t in o 15
SqlAlchemy: Mapping imperativo
L'approccio Imperative Mapping in SQLAlchemy (noto anche come "Classical Mapping") è un approccio basato sul
principio della separazione delle competenze (Separation of Concerns) e separa completamente la definizione delle
classi Python dalla definizione delle tabelle del database.
In questo caso il mapping tra tabelle e classi viene fatto su due file diversi e poi associate tramite una funzione
registry.map_imperatively().
from sqlalchemy import Table, Column, Integer, String, MetaData
from [Link] import registry
• Caratteristiche:
reg = registry() Totale disaccoppiamento tra il modello
metadata = MetaData() dati del database e il modello a oggetti di
# 1. Definizione della Tabella
user_table = Table( "user",
Python.
metadata, • Vantaggio:
Column("id", Integer, primary_key=True), Utile se hai classi esistenti che non
Column("name", String, nullable=False),
) possono ereditare da una base specifica o
# 2. Definizione della Classe POPO (Plain Old Python Object) se vuoi mantenere la logica di business
class User: completamente isolata dalla struttura del
pass
# 3. invocazione della funzione mapper (Mapping Imperativo ) DB.
reg.map_imperatively(User, user_table) • Sintassi: Richiede l'uso esplicito
dell'oggetto Table e dei metadati.
P ro f . A rm a n do Va le n t in o 16
SqlAlchemy: Mapping imperativo
# 4. Configurazione dell'Engine e della Sessione
from sqlalchemy import create_engine
from [Link] import sessionmaker
engine = create_engine("sqlite:///nome_database.db")
metadata.create_all(engine) # Crea le tabelle nel DB
Session = sessionmaker(bind=engine)
session = Session()
P ro f . A rm a n do Va le n t in o 17
SqlAlchemy: Mapping dichiarativo
I principi di progettazione del mapping dichiarativo si basano sull'idea di definire simultaneamente la
struttura logica dell'oggetto (classi) e la sua rappresentazione fisica nel database (Tabelle).
#1. Definizione della Base e dei Tipi
#Tutte le classi mappate devono ereditare da una classe base
from [Link] import DeclarativeBase, Mapped, mapped_column
from sqlalchemy import create_engine
class Base(DeclarativeBase):
pass • Co-locazione:
#2. Creazione della Classe Modello La definizione della tabella e la classe
class User(Base): #eredita da Base Python sono unificate.
__tablename__ = "user" • Convenzione sulla Configurazione:
#3. Definizione degli Attributi (Colonne)
id: Mapped[int] = mapped_column(primary_key=True)
L'approccio sfrutta convenzioni
name: Mapped[str] = mapped_column(nullable=False) intelligenti per semplificare la
configurazione. Ad esempio, il nome
#4. Configurazione dell'Engine e Schema della tabella viene spesso dedotto
engine = create_engine("sqlite:///nome_database.db,echo=True)
#5. Crea tutte le tabelle nel database automaticamente dal nome della classe.
[Link].create_all(engine) • Sintassi: Si definiscono i tipi tramite
Mapped e mapped_column.
P ro f . A rm a n do Va le n t in o 18
SqlAlchemy: Mapping dichiarativo
#[Link] della Sessione
from [Link] import sessionmaker
Session = sessionmaker(bind=engine)
session = Session()
P ro f . A rm a n do Va le n t in o 19
SqlAlchemy: installazione e verifica
Installazione di SQLAlchemy pip install sqlalchemy
from sqlalchemy import create_engine, Column, Integer, String
Verificare l'Installazione from [Link] import declarative_base, sessionmaker
Base = declarative_base()
engine = create_engine('sqlite:///[Link]')
Session = sessionmaker(bind=engine)
session = Session()
[Link].create_all(engine)
print("SQLAlchemy e SQLite installati e configurati correttamente!")
Importa moduli e funzionalità da SQLAlchemy.
from sqlalchemy import create_engine, MetaData ,Table, Column, Integer, String, Float, ForeignKey
from [Link] import Session, sessionmaker, relationship, registry
P ro f . A rm a n do Va le n t in o 20
Licenza
Quest'opera è distribuita con Licenza Creative Commons Attribuzione - Non commerciale - Non opere derivate 4.0 Internazionale.
P ro f . A rm a n do Va le n t in o 21