TP done async/sync

This commit is contained in:
Johan
2025-12-15 16:05:03 +01:00
parent f042f8e3e2
commit cac4fd62bb
3 changed files with 54 additions and 59 deletions

3
.idea/misc.xml generated
View File

@@ -1,4 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<project version="4"> <project version="4">
<component name="Black">
<option name="sdkName" value="Poetry (m01_tp01_asyncio)" />
</component>
<component name="ProjectRootManager" version="2" project-jdk-name="Poetry (m01_tp01_asyncio)" project-jdk-type="Python SDK" /> <component name="ProjectRootManager" version="2" project-jdk-name="Poetry (m01_tp01_asyncio)" project-jdk-type="Python SDK" />
</project> </project>

View File

@@ -74,21 +74,23 @@ async def download_and_save(
url (str): l'URL de l'image à télécharger. url (str): l'URL de l'image à télécharger.
output_dir (Path): le répertoire où sauvegarder l'image. output_dir (Path): le répertoire où sauvegarder l'image.
""" """
# TODO : votre code ici. Similaire à la version synchrone, mais avec `async`/`await`. filename = None
# 1. Utilisez un bloc `try...except` pour gérer les erreurs (ClientError, asyncio.TimeoutError, IOError). try:
# filename = url.split("/")[-1]
# 2. Dans le bloc `try` : output_path = output_dir / filename
# a. Extrayez le nom du fichier et construisez le chemin de sauvegarde (comme avant). logging.debug(f"Début du téléchargement -> {url}")
# b. Logguez le début du téléchargement. async with session.get(url, timeout=30) as response:
# c. Utilisez `async with session.get(url) as response:` pour effectuer la requête. response.raise_for_status()
# d. Vérifiez le statut de la réponse avec `response.raise_for_status()`. content = await response.read()
# e. Lisez le contenu de la réponse de manière asynchrone : `data = await response.read()`. logging.debug(f"Sauvegarde de {filename} sur {output_path}")
# f. Utilisez `async with aiofiles.open(path, "wb") as f:` pour ouvrir le fichier async with aiofiles.open(output_path, "wb") as f:
# sans bloquer la boucle événementielle. await f.write(content)
# g. Écrivez les données dans le fichier : `await f.write(data)`. logging.info(f"Image {filename} sauvegardée !")
# h. Logguez la confirmation de la sauvegarde. except ClientError as e:
# logging.error(f"Erreur {url}: {e}")
# 3. Dans les blocs `except`, logguez les erreurs spécifiques. except IOError as e:
file_ref = f"le fichier {filename}" if filename else "un fichier"
logging.error(f"Erreur d'écriture pour {file_ref}: {e}")
async def main() -> None: async def main() -> None:
@@ -103,19 +105,16 @@ async def main() -> None:
OUTPUT_DIR.mkdir(parents=True, exist_ok=True) OUTPUT_DIR.mkdir(parents=True, exist_ok=True)
logging.info(f"Le répertoire de sortie est : {OUTPUT_DIR}") logging.info(f"Le répertoire de sortie est : {OUTPUT_DIR}")
start_time = time.perf_counter()
# TODO : votre code ici. C'est ici que la magie de l'asynchronisme opère. async with aiohttp.ClientSession() as session:
# 1. Créez une session client avec `async with aiohttp.ClientSession() as session:`. tasks = [download_and_save(session, url, OUTPUT_DIR) for url in IMG_URLS]
# await asyncio.gather(*tasks)
# 2. À l'intérieur du `async with`, créez une liste de "tâches". Chaque tâche end_time = time.perf_counter()
# est un appel à votre coroutine `download_and_save`. duration = end_time - start_time
# Astuce : une compréhension de liste est parfaite pour ça. logging.info("-" * 40)
# Exemple : `tasks = [download_and_save(session, url, OUTPUT_DIR) for url in IMG_URLS]` logging.info("Tous les téléchargements sont terminés !")
# logging.info(f"Temps total d'exécution : {duration:.2f} secondes !")
# 3. Utilisez `asyncio.gather()` pour lancer toutes les tâches en parallèle et logging.info("-" * 40)
# attendre qu'elles se terminent toutes.
# La syntaxe est : `await asyncio.gather(*tasks)`
# (L'étoile `*` dépaquette la liste de tâches en arguments pour `gather`).
if __name__ == "__main__": if __name__ == "__main__":

View File

@@ -64,25 +64,20 @@ def download_and_save(session: requests.Session, url: str, output_dir: Path) ->
url (str): L'URL de l'image à télécharger. url (str): L'URL de l'image à télécharger.
output_dir (Path): Le répertoire où sauvegarder l'image. output_dir (Path): Le répertoire où sauvegarder l'image.
""" """
# TODO : votre code ici. Suivez ces étapes : filename = None
# 1. Utilisez un bloc `try...except` pour gérer les erreurs potentielles try:
# (RequestException, IOError). filename = url.split("/")[-1]
# output_path = output_dir / filename
# 2. Dans le bloc `try` : response = session.get(url, timeout=30)
# a. Extrayez le nom du fichier à partir de l'URL. response.raise_for_status()
# Astuce : `url.split("/")[-1]` est une méthode simple. with open(output_path, "wb") as f:
# b. Construisez le chemin de sauvegarde complet en utilisant `pathlib`. f.write(response.content)
# Exemple : `output_dir / nom_du_fichier` logging.info(f"Image {filename} sauvegardée !")
# c. Logguez le début du téléchargement. except RequestException as e:
# d. Effectuez une requête GET avec `session.get(url)`. Pensez à ajouter un timeout. logging.error(f"Erreur {url}: {e}")
# e. Vérifiez que la requête a réussi avec `response.raise_for_status()`. except IOError as e:
# f. Ouvrez le fichier de destination en mode écriture binaire ('wb') file_ref = f"le fichier {filename}" if filename else "un fichier"
# en utilisant un `with open(...)`. logging.error(f"Erreur d'écriture pour {file_ref}: {e}")
# g. Écrivez le contenu de la réponse (`response.content`) dans le fichier.
# h. Logguez la confirmation de la sauvegarde.
#
# 3. Dans les blocs `except`, logguez l'erreur de manière descriptive
# (ex: `logging.error(...)`).
def main() -> None: def main() -> None:
@@ -100,20 +95,18 @@ def main() -> None:
# `exist_ok=True` évite une erreur si le répertoire existe déjà. # `exist_ok=True` évite une erreur si le répertoire existe déjà.
OUTPUT_DIR.mkdir(parents=True, exist_ok=True) OUTPUT_DIR.mkdir(parents=True, exist_ok=True)
logging.info(f"Le répertoire de sortie est : {OUTPUT_DIR}") logging.info(f"Le répertoire de sortie est : {OUTPUT_DIR}")
start_time = time.perf_counter() start_time = time.perf_counter()
with requests.Session() as session:
# TODO : votre code ici. Suivez ces étapes : for url in IMG_URLS:
# 1. Utilisez un gestionnaire de contexte `with requests.Session() as session:` logging.info(f"Téléchargement de {url}...")
# pour créer une session qui sera utilisée pour toutes les requêtes. download_and_save(session, url, OUTPUT_DIR)
# Ceci optimise les connexions réseau. end_time = time.perf_counter()
# duration = end_time - start_time
# 2. À l'intérieur du `with`, faites une boucle `for` sur la liste `IMG_URLS`. logging.info("-" * 40)
# logging.info("Téléchargement terminé !")
# 3. Dans la boucle, appelez la fonction `download_and_save()` pour chaque URL, logging.info(f"Temps total d'exécution : {duration:.2f} secondes !")
# en lui passant la session, l'URL et le répertoire de sortie. logging.info("-" * 40)
if __name__ == "__main__": if __name__ == "__main__":
main() main()