Cours Python · Module 12: Projet final
Préparation à ta carrière
Dans cette leçon5
Félicitations ! Tu as terminé Python Safari. Tu as douze lieux derrière toi, mais un certificat seul n'a jamais fait embaucher personne. Un recruteur consacre quelques dizaines de secondes à ton CV, et un entretien technique comportera des questions qui vérifient si tu comprends ce que tu écris. Il est temps de transformer tes compétences en premier emploi. On va préparer un CV, un profil LinkedIn, des réponses aux questions typiques et une liste d'endroits où chercher des offres.
CV pour un développeur Python
Un bon CV de développeur est court et concret : coordonnées avec un lien vers GitHub, un résumé d'une phrase, des compétences regroupées par catégories et des projets avec leurs résultats. Voici un modèle :
1# John Smith
2Développeur Python | Spécialiste AI/ML
3
4john@example.com | linkedin.com/in/john | github.com/john
5
6## Résumé
7Développeur Python avec de l'expérience dans la création d'applications AI/ML.
8Spécialisation : systèmes RAG, FastAPI, Machine Learning.
9
10## Compétences
11
12**Langages :** Python, JavaScript, SQL
13**Frameworks :** FastAPI, Django, React
14**AI/ML :** LlamaIndex, LangChain, PyTorch, scikit-learn
15**Bases de données :** PostgreSQL, Qdrant, Redis
16**Outils :** Docker, Git, GitHub Actions, AWS
17
18## Projets
19
20### AI Document Assistant | [GitHub](link) | [Démo](link)
21- Système RAG pour rechercher dans les documents
22- Tech : FastAPI, LlamaIndex, Qdrant, OpenAI
23- Résultats : temps de réponse <2s, précision de 92%
24
25### ML Pipeline | [GitHub](link)
26- Pipeline ML de bout en bout avec MLflow
27- Tech : scikit-learn, XGBoost, MLflow, Docker
28- Résultats : amélioration de 15% de la précision
29
30## Formation
31
32**Python Safari** - CodeWorlds (2024)
33- Cours Python et IA en 12 modules
34- Projet Capstone : AI Document Assistant
35
36## Certifications
37- [Nom du certificat]La section Projets compte plus que la section Formation, car elle montre ce que tu as construit. Les chiffres des lignes « Résultats » illustrent le format, ce ne sont pas des valeurs toutes faites : n'y mets que ce que tu as vraiment mesuré dans ton projet. Un recruteur peut t'interroger sur chaque chiffre en entretien. En début de carrière, garde ton CV sur une page et envoie-le en PDF pour que la mise en page ne se casse pas de l'autre côté.
Optimisation de LinkedIn
LinkedIn fonctionne comme un moteur de recherche, les recruteurs cherchent par mots-clés dans le titre et la section À propos. Le titre n'est pas seulement un intitulé de poste, c'est une liste de technologies :
1## Titre (Headline)
2Développeur Python | AI/ML | FastAPI | Je construis des applications intelligentes
3
4## À propos
5Développeur Python passionné, spécialisé dans les applications d'IA.
6
7Systèmes RAG et intégration de LLM
8FastAPI et Python asynchrone
9Pipelines de Machine Learning
10
11En cours de développement : AI Document Assistant - recherche sémantique dans les documents.
12
13Ouvert aux opportunités en développement AI/ML.
14
15## Sélection (Featured)
16- Lien vers ton meilleur projet
17- Un article/post sur une technologie
18- Un certificat/diplômeLa section Sélection (Featured) est l'endroit pour le lien vers ton meilleur projet. Un seul projet bien décrit avec une démo en dit plus qu'une liste de vingt technologies. Ajoute aussi un lien vers GitHub dans tes coordonnées, car c'est précisément là que le recruteur ira chercher les preuves de tes compétences.
Préparation à l'entretien
Un entretien technique pour un développeur Python couvre en général quatre domaines. Passons-les en revue un par un. Le premier, ce sont les fondamentaux du langage, et la question classique porte sur le GIL :
1# Questions techniques typiques
2
3# 1. Fondamentaux de Python
4def explain_gil():
5 """
6 GIL (Global Interpreter Lock) - un mécanisme de CPython
7 qui n'autorise qu'un seul thread à exécuter
8 du bytecode Python à un instant donné.
9
10 Solutions :
11 - multiprocessing pour les tâches CPU-bound
12 - asyncio pour les tâches I/O-bound
13 - interpréteurs alternatifs (PyPy)
14 """
15 passDans le CPython standard, le GIL (Global Interpreter Lock) n'autorise qu'un seul thread à la fois à exécuter du bytecode Python. Les threads n'accélèrent donc pas les calculs sur le processeur. Il vaut la peine d'ajouter que depuis Python 3.13 il existe un build free-threaded séparé, sans GIL (PEP 703), officiellement pris en charge en 3.14 (PEP 779) mais toujours optionnel. Le deuxième domaine, c'est la programmation asynchrone :
1# 2. Python asynchrone
2async def explain_async():
3 """
4 async/await - le modèle de concurrence de Python.
5 - async def - définit une coroutine
6 - await - attend le résultat d'une opération async
7 - Idéal pour les opérations I/O-bound
8 """
9 passLe module asyncio fournit la prise en charge d'async/await. La règle à retenir : async/await pour les opérations I/O-bound (réseau, base de données, fichiers), multiprocessing pour le travail CPU-bound. Le troisième domaine, ce sont les design patterns, que tu connais depuis la leçon sur l'architecture :
1# 3. Design Patterns
2def explain_patterns():
3 """
4 Patterns les plus importants :
5 - Repository Pattern - abstraction de l'accès aux données
6 - Dependency Injection - couplage faible
7 - Factory Pattern - création d'objets
8 - Observer Pattern - réactivité
9 """
10 passEn entretien, le nom du pattern ne suffit pas, montre un exemple tiré de ton propre projet, comme DocumentRepository. Le quatrième domaine, c'est le system design :
1# 4. System Design
2def design_rag_system():
3 """
4 Composants :
5 1. API Gateway - routage, auth
6 2. RAG Service - traitement des requêtes
7 3. Vector Database - stockage des embeddings
8 4. LLM Service - génération de texte
9 5. Cache - Redis pour les requêtes fréquentes
10 6. Monitoring - Prometheus + Grafana
11 """
12 passC'est exactement l'architecture de ton projet capstone. Explique pourquoi tu as choisi chaque composant, car c'est là-dessus qu'on va te questionner.
Il y aura aussi des questions sur les outils. Tu crées un environnement virtuel avec python -m venv .venv et tu l'actives sous Linux et macOS avec source .venv/bin/activate. Le fichier requirements.txt liste les dépendances avec leurs versions. Dans FastAPI, Pydantic valide les données et définit les modèles de requête et de réponse. Par défaut, pytest découvre les fichiers test_*.py et *_test.py.
Où chercher un emploi
Dernière étape : savoir où chasser les offres. Les sites d'emploi évoluent avec le temps (GitHub Jobs et Stack Overflow Jobs n'existent plus), alors considère cette liste comme un point de départ :
1## Développeur Python Junior/Mid
2
31. **LinkedIn Jobs** - la meilleure source
42. **NoFluffJobs** - marché IT polonais
53. **JustJoinIT** - startups et grandes entreprises
64. **Bulldogjob** - site polonais d'offres IT
75. **Wellfound** (anciennement AngelList Talent) - startups, offres internationales
8
9## Freelance
10
111. **Upwork** - projets à long terme
122. **Toptal** - premium, nécessite une vérification
133. **Fiverr** - projets plus petits
14
15## Open Source
16
171. Contribue aux projets que tu utilises
182. Construis ta réputation
193. Réseaute avec d'autres développeursL'open source est une voie souvent sous-estimée : une contribution à une bibliothèque que tu utilises est une preuve publique de tes compétences et un moyen de rencontrer des développeurs expérimentés.
Prochaines étapes
Le plan pour les semaines à venir est simple : termine le projet Capstone, publie-le sur GitHub, mets à jour ton CV et ton LinkedIn, postule à des offres et continue d'apprendre. Mon conseil : n'attends pas de te sentir « prêt ». Postule dès que tu as un projet solide, car les entretiens eux-mêmes sont le meilleur entraînement.
Souviens-toi : ce n'est pas la fin, c'est le début de ton aventure Python, et chaque future expédition commence par la carte que tu as tracée dans ce module.
Code de cette leçon : main.py
1# ===========================================
2# Safari Capstone : Couche de service principale
3# ===========================================
4# Implémente le service de logique métier principal qui
5# gère les opérations sur la faune et les analyses.
6
7from dataclasses import dataclass, field
8from datetime import datetime
9from typing import Optional
10import json
11
12# --- Modèles ---
13@dataclass
14class Animal:
15 animal_id: str
16 species: str
17 name: str
18 weight_kg: float
19 region: str
20
21@dataclass
22class Observation:
23 obs_id: str
24 animal_id: str
25 latitude: float
26 longitude: float
27 observer: str
28 timestamp: str = ""
29
30# --- Repository ---
31class AnimalRepository:
32 def __init__(self):
33 self._data = {}
34
35 def save(self, animal): self._data[animal.animal_id] = animal
36 def get(self, aid): return self._data.get(aid)
37 def get_all(self): return list(self._data.values())
38 def delete(self, aid): return self._data.pop(aid, None) is not None
39 def find_by_species(self, sp):
40 return [a for a in self._data.values() if a.species.lower() == sp.lower()]
41
42# --- Service principal ---
43class SafariService:
44 """Logique métier principale du système de gestion du safari."""
45
46 def __init__(self, repo: AnimalRepository):
47 self.repo = repo
48 self.observations: list[Observation] = []
49 self._next_obs_id = 1
50
51 def register_animal(self, species, name, weight_kg, region) -> Animal:
52 """Enregistre un nouvel animal dans le système."""
53 prefix = species[:2].upper()
54 count = len(self.repo.find_by_species(species)) + 1
55 animal_id = f"{prefix}-{count:03d}"
56 animal = Animal(animal_id, species, name, weight_kg, region)
57 self.repo.save(animal)
58 return animal
59
60 def record_observation(self, animal_id, lat, lon, observer) -> Optional[Observation]:
61 """Enregistre une nouvelle observation de faune sauvage."""
62 animal = self.repo.get(animal_id)
63 if not animal:
64 return None
65 obs = Observation(
66 obs_id=f"OBS-{self._next_obs_id:04d}",
67 animal_id=animal_id,
68 latitude=lat,
69 longitude=lon,
70 observer=observer,
71 timestamp=datetime.now().isoformat()
72 )
73 self.observations.append(obs)
74 self._next_obs_id += 1
75 return obs
76
77 def get_species_stats(self) -> dict:
78 """Renvoie les statistiques de population groupées par espèce."""
79 stats = {}
80 for animal in self.repo.get_all():
81 species = animal.species
82 if species not in stats:
83 stats[species] = {"count": 0, "total_weight": 0.0, "regions": set()}
84 stats[species]["count"] += 1
85 stats[species]["total_weight"] += animal.weight_kg
86 stats[species]["regions"].add(animal.region)
87 # Convertir les ensembles en listes pour la compatibilité JSON
88 for sp in stats:
89 stats[sp]["avg_weight"] = round(stats[sp]["total_weight"] / stats[sp]["count"], 1)
90 stats[sp]["regions"] = list(stats[sp]["regions"])
91 return stats
92
93 def get_observation_count(self, animal_id: str) -> int:
94 """Compte les observations pour un animal précis."""
95 return sum(1 for o in self.observations if o.animal_id == animal_id)
96
97 def generate_report(self) -> str:
98 """Génère un rapport de synthèse de toutes les données de la faune."""
99 stats = self.get_species_stats()
100 total_animals = self.repo.get_all()
101 lines = [
102 "=== Safari Wildlife Report ===",
103 f"Total animals tracked: {len(total_animals)}",
104 f"Total observations: {len(self.observations)}",
105 f"Species tracked: {len(stats)}",
106 ""
107 ]
108 for species, data in stats.items():
109 lines.append(f"{species}: {data['count']} animals, "
110 f"avg {data['avg_weight']} kg, "
111 f"regions: {', '.join(data['regions'])}")
112 return "\n".join(lines)
113
114# --- Démo ---
115repo = AnimalRepository()
116service = SafariService(repo)
117
118# Enregistrer des animaux
119service.register_animal("Lion", "Simba", 195.0, "Savanna")
120service.register_animal("Lion", "Nala", 130.0, "Savanna")
121service.register_animal("Elephant", "Tembo", 5200.0, "Forest")
122service.register_animal("Cheetah", "Duma", 52.0, "Grassland")
123
124# Enregistrer des observations
125service.record_observation("LI-001", -2.33, 34.83, "Dr. Darwin")
126service.record_observation("LI-001", -2.34, 34.84, "Dr. Darwin")
127service.record_observation("EL-001", -2.41, 34.92, "Ranger Kate")
128
129# Générer un rapport
130print(service.generate_report())
131print(f"\nObservations de Simba : {service.get_observation_count('LI-001')}")
132print(f"\nStats par espèce :")
133print(json.dumps(service.get_species_stats(), indent=2))
134
135# TODO : Ajoute une méthode pour trouver l'animal le plus observé
136# def most_observed_animal(self) -> Optional[str]:
137# counts = {}
138# for obs in self.observations:
139# counts[obs.animal_id] = counts.get(obs.animal_id, 0) + 1
140# if not counts:
141# return None
142# return max(counts, key=counts.get)
143
144# TODO : Ajoute une fonctionnalité d'export des données
145# def export_data(self, format="json") -> str:
146# data = {
147# "animals": [vars(a) for a in self.repo.get_all()],
148# "observations": [vars(o) for o in self.observations],
149# "stats": self.get_species_stats()
150# }
151# return json.dumps(data, indent=2, default=str)
152Tu as repéré une erreur dans cette leçon ?
Teste tes connaissances
Réponds aux questions de cette leçon. Choisis une réponse pour voir tout de suite si elle est correcte.
1. Qu'est-ce que le GIL en Python ?
2. Que fournit asyncio en Python ?
Voici 2 des 5 questions de cette leçon. Réponds aux autres dans le jeu.
Tâches pratiques dans le jeu
- Tri horizontal
Range la commande pour créer un environnement virtuel Python :
- Clique dans l'ordre
Clique sur les éléments pour construire la commande d'activation de venv (Linux/Mac) :
- Éditeur de code
Écris une configuration GitHub Actions pour le CI d'un projet Python
- Éditeur de code
Crée la structure initiale du projet Capstone avec le module principal et la configuration
- Éditeur de code
Implémente le service d'IA principal avec une méthode de prédiction
- Éditeur de code
Crée une couche API REST avec FastAPI pour le projet Capstone
- Éditeur de code
Écris des tests pour le projet Capstone avec pytest