diff --git a/.idea/misc.xml b/.idea/misc.xml index 19d1aff..2bda3c5 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -1,4 +1,7 @@ + + \ No newline at end of file diff --git a/src/tp_asyncio/async_downloader.py b/src/tp_asyncio/async_downloader.py index ddae2e0..d45cb9a 100644 --- a/src/tp_asyncio/async_downloader.py +++ b/src/tp_asyncio/async_downloader.py @@ -74,21 +74,23 @@ async def download_and_save( url (str): l'URL de l'image à télécharger. output_dir (Path): le répertoire où sauvegarder l'image. """ - # TODO : votre code ici. Similaire à la version synchrone, mais avec `async`/`await`. - # 1. Utilisez un bloc `try...except` pour gérer les erreurs (ClientError, asyncio.TimeoutError, IOError). - # - # 2. Dans le bloc `try` : - # a. Extrayez le nom du fichier et construisez le chemin de sauvegarde (comme avant). - # b. Logguez le début du téléchargement. - # c. Utilisez `async with session.get(url) as response:` pour effectuer la requête. - # d. Vérifiez le statut de la réponse avec `response.raise_for_status()`. - # e. Lisez le contenu de la réponse de manière asynchrone : `data = await response.read()`. - # f. Utilisez `async with aiofiles.open(path, "wb") as f:` pour ouvrir le fichier - # sans bloquer la boucle événementielle. - # g. Écrivez les données dans le fichier : `await f.write(data)`. - # h. Logguez la confirmation de la sauvegarde. - # - # 3. Dans les blocs `except`, logguez les erreurs spécifiques. + filename = None + try: + filename = url.split("/")[-1] + output_path = output_dir / filename + logging.debug(f"Début du téléchargement -> {url}") + async with session.get(url, timeout=30) as response: + response.raise_for_status() + content = await response.read() + logging.debug(f"Sauvegarde de {filename} sur {output_path}") + async with aiofiles.open(output_path, "wb") as f: + await f.write(content) + logging.info(f"Image {filename} sauvegardée !") + except ClientError as e: + logging.error(f"Erreur {url}: {e}") + 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: @@ -103,19 +105,16 @@ async def main() -> None: OUTPUT_DIR.mkdir(parents=True, exist_ok=True) logging.info(f"Le répertoire de sortie est : {OUTPUT_DIR}") - - # TODO : votre code ici. C'est ici que la magie de l'asynchronisme opère. - # 1. Créez une session client avec `async with aiohttp.ClientSession() as session:`. - # - # 2. À l'intérieur du `async with`, créez une liste de "tâches". Chaque tâche - # est un appel à votre coroutine `download_and_save`. - # Astuce : une compréhension de liste est parfaite pour ça. - # Exemple : `tasks = [download_and_save(session, url, OUTPUT_DIR) for url in IMG_URLS]` - # - # 3. Utilisez `asyncio.gather()` pour lancer toutes les tâches en parallèle et - # 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`). + start_time = time.perf_counter() + async with aiohttp.ClientSession() as session: + tasks = [download_and_save(session, url, OUTPUT_DIR) for url in IMG_URLS] + await asyncio.gather(*tasks) + end_time = time.perf_counter() + duration = end_time - start_time + logging.info("-" * 40) + logging.info("Tous les téléchargements sont terminés !") + logging.info(f"Temps total d'exécution : {duration:.2f} secondes !") + logging.info("-" * 40) if __name__ == "__main__": diff --git a/src/tp_asyncio/sync_downloader.py b/src/tp_asyncio/sync_downloader.py index 67c8755..f692169 100644 --- a/src/tp_asyncio/sync_downloader.py +++ b/src/tp_asyncio/sync_downloader.py @@ -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. output_dir (Path): Le répertoire où sauvegarder l'image. """ - # TODO : votre code ici. Suivez ces étapes : - # 1. Utilisez un bloc `try...except` pour gérer les erreurs potentielles - # (RequestException, IOError). - # - # 2. Dans le bloc `try` : - # a. Extrayez le nom du fichier à partir de l'URL. - # Astuce : `url.split("/")[-1]` est une méthode simple. - # b. Construisez le chemin de sauvegarde complet en utilisant `pathlib`. - # Exemple : `output_dir / nom_du_fichier` - # c. Logguez le début du téléchargement. - # d. Effectuez une requête GET avec `session.get(url)`. Pensez à ajouter un timeout. - # e. Vérifiez que la requête a réussi avec `response.raise_for_status()`. - # f. Ouvrez le fichier de destination en mode écriture binaire ('wb') - # en utilisant un `with open(...)`. - # 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(...)`). + filename = None + try: + filename = url.split("/")[-1] + output_path = output_dir / filename + response = session.get(url, timeout=30) + response.raise_for_status() + with open(output_path, "wb") as f: + f.write(response.content) + logging.info(f"Image {filename} sauvegardée !") + except RequestException as e: + logging.error(f"Erreur {url}: {e}") + 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}") def main() -> None: @@ -100,20 +95,18 @@ def main() -> None: # `exist_ok=True` évite une erreur si le répertoire existe déjà. OUTPUT_DIR.mkdir(parents=True, exist_ok=True) logging.info(f"Le répertoire de sortie est : {OUTPUT_DIR}") - start_time = time.perf_counter() - - # TODO : votre code ici. Suivez ces étapes : - # 1. Utilisez un gestionnaire de contexte `with requests.Session() as session:` - # pour créer une session qui sera utilisée pour toutes les requêtes. - # Ceci optimise les connexions réseau. - # - # 2. À l'intérieur du `with`, faites une boucle `for` sur la liste `IMG_URLS`. - # - # 3. Dans la boucle, appelez la fonction `download_and_save()` pour chaque URL, - # en lui passant la session, l'URL et le répertoire de sortie. + with requests.Session() as session: + for url in IMG_URLS: + logging.info(f"Téléchargement de {url}...") + download_and_save(session, url, OUTPUT_DIR) + end_time = time.perf_counter() + duration = end_time - start_time + logging.info("-" * 40) + logging.info("Téléchargement terminé !") + logging.info(f"Temps total d'exécution : {duration:.2f} secondes !") + logging.info("-" * 40) if __name__ == "__main__": main() -