Python
Opérations sur les fichiers, pathlib, one-liners et bases SQLite pour le quotidien.
đ Fichiers & pathlib
Lecture / écriture simple
import datetime
# Lecture complĂšte â le contexte gĂšre la fermeture
with open('data.txt') as f:
contenu = f.read()
# Ăcriture (Ă©crase)
with open('output.txt', 'w') as f:
f.write('ligne 1\nligne 2\n')
# Ăcriture append avec horodatage
with open('log.txt', 'a') as f:
f.write(f'[{datetime.datetime.now():%Y-%m-%d %H:%M}] info\n')Parcours de répertoire avec pathlib
from pathlib import Path
# Tous les fichiers .py du projet, triés
fichiers = sorted(Path('.').rglob('*.py'))
# Taille totale d'un dossier (cohérent avec os.stat)
taille = sum(p.stat().st_size for p in Path('docs').rglob('*') if p.is_file())
print(f'{taille / 1024:.1f} Ko')
# Créer une arborescence (Parent / Enfant)
racine = Path('/var/log')
(justes := list(racine.glob('*.log')))[:3] # 3 premiers .logPitfall :
Path.rglob('*')inclut les dossiers. Filtrer avec.is_file()pour ne garder que les fichiers.
Copie / déplacement / suppression
import shutil
from pathlib import Path
src = Path('source.txt')
dst = Path('archive/source.txt')
# Copie (bit à bit, préserve les métadonnées)
shutil.copy2(src, dst)
# Déplacement
shutil.move('temp/', '/tmp/processed/')
# Suppression récursive sûre (équivalent de `rm -rf`)
if Path('trash').exists():
shutil.rmtree('trash')đ Environnement & chemin
Variables dâenvironnement
import os
# Lecture avec valeur par défaut (pas de KeyError)
db_url = os.getenv('DATABASE_URL', 'sqlite:///local.db')
# Lister les variables contenant un préfixe
prefix = 'MYAPP_'
config = {k: v for k, v in os.environ.items() if k.startswith(prefix)}
# Définit la valeur si la clé n'existe pas encore
os.environ.setdefault('LOG_LEVEL', 'INFO')Chemins portables
from pathlib import Path
# Chemin absolu résolu (symlinks suivis)
dossier_projet = Path(__file__).resolve().parent.parent
# Chemin relatif depuis un autre dossier
relative = dossier_projet.relative_to(Path.home())
# PosixPath('projects/mon-app')
# Extensions et suffixes
p = Path('archive.tar.gz')
p.stem # 'archive'
p.suffix # '.gz'
p.suffixes # ['.tar', '.gz']
p.with_suffix('.zip') # archive.tar.zipPitfall :
os.path.join()fonctionne aussi, maispathlibĂ©vite les problĂšmes de sĂ©parateurs sur Windows. PrivilĂ©gierpathlibquand câest possible.
⥠One-liners
List comprehensions & conditions
# pairs & odds
nombres = list(range(20))
pairs = [x for x in nombres if x % 2 == 0]
impairs = [x for x in nombres if x % 2 != 0]
# Dictionnaire Ă partir de deux listes
clefs = ['nom', 'age', 'role']
valeurs = ['Alice', 30, 'dev']
dico = dict(zip(clefs, valeurs))
# {'nom': 'Alice', 'age': 30, 'role': 'dev'}Dict unpacking & fusion
# Fusion de dicts â Python 3.9+
pref = {'port': 3000, 'host': 'localhost'}
env = {'port': 8080, 'debug': True}
config = {**pref, **env}
# {'port': 8080, 'host': 'localhost', 'debug': True}
# env écrase pref sur les clés en conflit
# Deep merge simple (2 niveaux max)
def merge_deep(a, b):
for k, v in b.items():
if k in a and isinstance(a[k], dict) and isinstance(v, dict):
merge_deep(a[k], v)
else:
a[k] = v
return aFormatage de chaĂźnes
# f-string (Python 3.6+)
prenom, age = 'Alice', 30
message = f'Bonjour {prenom}, tu as {age} ans'
# Alignement / remplissage
f'{42:>10}' # ' 42'
f'{0.123:.2f}' # '0.12'
f'{255:x}' # 'ff' (hex)
f'{1024:b}' # '10000000000' (binaire)
# string method alternatifs
' hello '.strip() # 'hello'
'HELLO'.casefold() # 'hello' ( NFC-safe )
'ab-cd'.removeprefix('ab-') # 'cd' (3.9+)
'.hello'.removesuffix('.hi') # 'hello' (3.9+)đïž SQLite â bases lĂ©gĂšres
Connexion & requĂȘtes simples
import sqlite3
db = sqlite3.connect('app.db')
db.row_factory = sqlite3.Row # accéder par nom de colonne
# Une requĂȘte paramĂ©trĂ©e (Ă©vite le SQL injection)
with db:
db.execute(
'INSERT INTO users (nom, email) VALUES (?, ?)',
('Alice', 'alice@example.com')
)
# Fetch
for row in db.execute('SELECT nom, email FROM users'):
print(f'{row["nom"]} <{row["email"]}>')
# Comptage rapide
compte = db.execute('SELECT COUNT(*) FROM users').fetchone()[0]
print(f'{compte} utilisateur(s)')RequĂȘtes avec paramĂštres
# â Jamais faire â SQL injection risquĂ©e
db.execute(f"SELECT * FROM users WHERE nom = '{nom}'")
# â
Toujours faire â paramĂštres positionnels
db.execute('SELECT * FROM users WHERE nom = ?', (nom,))
# â
ou noms explicites (Python 3.6+)
db.execute('SELECT * FROM users WHERE nom = :nom', {'nom': nom})Pitfall : sans
db.row_factory = sqlite3.Row, les lignes ne sont accessibles que par index (row[0]), pas par nom de colonne. Oublier de définirrow_factoryrend le code fragile quand le schéma évolue.
đ Logging & dĂ©buggage rapide
Niveaux de log
import logging
logging.basicConfig(
level=logging.DEBUG,
format='%(asctime)s [%(levelname)s] %(name)s: %(message)s',
)
logger = logging.getLogger(__name__)
logger.debug('Var intermédiaire: %s', ma_var)
logger.info('Point d\'entrée fonction X')
logger.warning('Champ manquant: %s', champ)
logger.error('Ăchec connexion DB: %s', exc)Variables locales en dĂ©bug
# afficher tout l'état courant sans pprinter manuellement
import sys
def debug():
'''Imprime le frame d'appel actuel â Ă appeler dans la fonction Ă debugger.'''
frame = sys._getframe(1)
for nom, valeur in sorted(frame.f_locals.items()):
print(f' {nom} = {valeur!r}')# Usage :
def traiter(donnees):
for item in donnees:
debug() # â envoie les vars locales au stderr
resultat = calcul(item)