TP done async/sync
This commit is contained in:
3
.idea/misc.xml
generated
3
.idea/misc.xml
generated
@@ -1,4 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<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" />
|
||||
</project>
|
||||
@@ -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__":
|
||||
|
||||
@@ -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()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user