"- Manipuler les dictionnaires et les chaînes de caractères\n",
"- Utiliser la bibliothèque de tracés graphiques matplotlib\n",
"- Utiliser un IDE (Spyder)\n",
"- Exécuter un fichier script\n",
"- Gérer les arguments de la ligne de commande"
"- Exécuter un fichier script en gérant les arguments de la ligne de commande"
]
},
{
...
...
@@ -30,7 +29,7 @@
"source": [
"## Exercice\n",
"\n",
"Exploiter les données du site [http://www.prevision-meteo.ch](http://www.prevision-meteo.ch) pour tracer l'évolution horaire de la température à Strasbourg aujourd'hui.\n",
"Exploiter les données du site <https://www.prevision-meteo.ch> pour tracer l'évolution horaire de la température à Strasbourg aujourd'hui.\n",
"\n",
" "
]
...
...
@@ -45,7 +44,7 @@
"source": [
"### Ouverture du fichier de prévisions\n",
"\n",
"Le site [https://www.prevision-meteo.ch](https://www.prevision-meteo.ch) fournit des prévisions sous forme de fichier au format [json](https://fr.wikipedia.org/wiki/JavaScript_Object_Notation). On veut récupérer les données relatives à Strasbourg avec la méthode `urlopen()` du module `urllib.request`."
"Le site <https://www.prevision-meteo.ch> fournit des prévisions sous forme de fichier au format [json](https://fr.wikipedia.org/wiki/JavaScript_Object_Notation). On veut récupérer les données relatives à Strasbourg avec la méthode `urlopen()` du module `urllib.request`."
]
},
{
...
...
@@ -279,7 +278,7 @@
"outputs": [],
"source": [
"# Décommenter la ligne ci-dessous\n",
"%save today_stras.py 1-12"
"%save today_stras.py 1-10"
]
},
{
...
...
@@ -300,7 +299,7 @@
"4. ordonner la liste selon les heures croissantes\n",
"5. convertir la liste en un *numpy array* `t` avec la méthode `numpy.array()`\n",
"6. Transposer `t` pour obtenir le tableau `[[array of hours], [array of temperatures]]`\n",
"7. réaliser un tracé matplotlib en suivant [ce tutoriel](http://matplotlib.org/users/pyplot_tutorial.html) ou en intégrant les lignes de code suivantes : "
"7. réaliser un tracé matplotlib en suivant [ce tutoriel](https://matplotlib.org/stable/tutorials/introductory/pyplot.html) ou en intégrant les lignes de code suivantes : "
]
},
{
...
...
@@ -353,7 +352,7 @@
},
"source": [
"Pas si vite ! Êtes-vous sûr ? Vraiment ? \n",
"Alors rendez-vous dans [exos/meteo_json.py](exos/meteo_json.py)"
"Alors rendez-vous dans [exos/correction/meteo_json.py](exos/correction/meteo_json.py)"
]
},
{
...
...
@@ -361,14 +360,31 @@
"metadata": {
"slideshow": {
"slide_type": "slide"
},
}
},
"source": [
"## Exercice sur les fonctions\n",
"\n",
"À partir de [`exos/correction/meteo_json.py`](exos/correction/meteo_json.py), écrivez le programme `meteo_json_func.py` qui contient une fonction `plot_day_tempe()` admettant deux arguments :\n",
"\n",
"- `day_key` : un entier représentant le jour visé (`0`: aujourd'hui, `1`: demain, `2`: après-demain...)\n",
"- `city_name`: une chaîne de caractère de la ville recherchée"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"solution2": "hidden",
"solution2_first": true
},
"outputs": [],
"source": [
"## Exercice sur les fonctions\n",
"# Pour tester votre script dans cette cellule, décommenter les lignes suivantes \n",
"# et redémarrer le noyau avant chaque modification:\n",
"\n",
"Modifiez le programme météo en créant une fonction qui admet un des jours disponibles comme argument (aujourd'hui, demain, après-demain...)"
"#from meteo_json_func import plot_day_tempe\n",
"#plot_day_tempe(2, city_name='Marseille')"
]
},
{
...
...
@@ -381,7 +397,20 @@
},
"source": [
"Pas si vite ! Êtes-vous sûr ? Vraiment ? \n",
"Alors allez voir une proposition de solution dans [exos/meteo_json_func.py](exos/meteo_json_func.py)"
"Alors allez voir une proposition de solution dans [exos/correction/meteo_json_func.py](exos/correction/meteo_json_func.py)"
" help='sum the integers (default: find the max)')\n",
"print(type(parser))"
"%run test_module.py"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"La variable `__name__` vaut `__main__`."
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"Importons maintenant le fichier comme un module."
]
},
{
...
...
@@ -538,24 +558,63 @@
"metadata": {},
"outputs": [],
"source": [
"# Sans \"--sum\"\n",
"args = parser.parse_args(['2', '5'])\n",
"print(args.accumulate(args.integers))"
"import test_module"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Le bloc qui appelle la fonction `main()` n'est pas exécuté. En revanche cette fonction est accessible à la demande :"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"test_module.main()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Cette fois-ci, la variable `__name__` vaut `test_module`, c'est-à-dire le nom du module importé.\n",
"\n",
"> Plus d'information sur `__name__` dans la [doc officielle](https://docs.python.org/fr/3/library/__main__.html)."
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"### Gestion des arguments de la ligne de commande\n",
"\n",
"Afin de positionner les paramètres d'un script à exécuter (noms de fichier, taille du problème, etc.), on a le choix entre :\n",
"\n",
"- éditer le script là où les variables sont définies : si c'est envisageable pour des tests ou dans le contexte d'un notebook, ça ne l'est pas pour un programme destiné à être exécuté plusieur fois avec des paramètres variables\n",
"- positionner des variables d'environnement qui peuvent être lues avec la fonction [`os.getenv()`](https://docs.python.org/fr/3/library/os.html#os.getenv) : le risque est de dissocier la définition des paramètres de l'exécution du programme.\n",
"- lire un fichier d'entrée, par exemple avec [`configparser`](https://docs.python.org/3/library/configparser.html). C'est particulièrement utile lorsque les paramètres sont nombreux et variés et que l'on souhaite faciliter la reproductibilité des exécutions mais ça demande d'éditer le fichier d'entrée à chaque changement de paramètre.\n",
"- interpréter les arguments de la ligne de commande : c'est la façon la plus souple d'exécuter un script avec des paramètres variables."
"Une façon très simple et très rapide créer une interface de ligne de commande (CLI en anglais) est d'utiliser la bibliothèque [`fire`](https://github.com/google/python-fire) développée par Google.\n",
"\n",
"C'est une biblithèque externe : commençons par l'installer avec pip."
]
},
{
...
...
@@ -564,12 +623,7 @@
"metadata": {},
"outputs": [],
"source": [
"# Certains arguments existent déjà\n",
"try:\n",
" parser.parse_args(['--help'])\n",
"except SystemExit:\n",
" # Pour éviter une erreur dans jupyter-notebook\n",
" pass"
"%pip install fire"
]
},
{
...
...
@@ -580,22 +634,86 @@
}
},
"source": [
"## Exercice\n",
"À titre d'exemple, le fichier [`exos/correction/meteo_json_func.py`](exos/correction/meteo_json_func.py) appelle `fire` dans son bloc final :\n",
"\n",
"Modifiez le programme météo pour qu'il prenne le(s) nom(s) de ville en argument(s) en utilisant le module `argparse`."
"```python\n",
"if __name__ == '__main__':\n",
" import fire\n",
" fire.Fire(plot_day_tempe)\n",
"```"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"`fire` utilise la signature et la docstring de la fonction `plot_day_tempe()` :"
"Alors allez voir une proposition de solution dans [exos/meteo_json_func_args.py](exos/meteo_json_func_args.py)"
"> Si on se limite ici à la présentation de `fire`, il faut mentionner l'existence du module [`argparse`](https://docs.python.org/3/library/argparse.html) qui fait partie de la bibliothèque standard.\n",
"Moins immédiate mais aussi plus souple, l'utilisation d'`argparse` est décrite dans ce [tutoriel](https://docs.python.org/3/howto/argparse.html#argparse-tutorial)."
]
},
{
...
...
@@ -619,27 +736,21 @@
}
},
"source": [
"## Suite de l'exercice\n",
"\n",
"- Laissez libre cours à vos idées et envies, par exemple :\n",
" - en cherchant à tracer l'évolution horaire de la température dans les 5 prochains jours\n",
" - etc.\n",
"\n",
"- Dans Spyder :\n",
" - testez le système de debugging\n",
" - testez le profiler\n",
"## Utilisation avancée de Spyder\n",
"\n",
"> À vous de faire la pluie et le beau temps !"
"- explorer le système de [debugging](https://docs.spyder-ide.org/5/panes/debugging.html)\n",
"- explorer le [profiler](https://docs.spyder-ide.org/5/panes/profiler.html)"
- Utiliser les modules de la bibliothèque standard pour récupérer des données via un service web.
- Manipuler les dictionnaires et les chaînes de caractères
- Utiliser la bibliothèque de tracés graphiques matplotlib
- Utiliser un IDE (Spyder)
- Exécuter un fichier script
- Gérer les arguments de la ligne de commande
- Exécuter un fichier script en gérant les arguments de la ligne de commande
%% Cell type:markdown id: tags:
## Exercice
Exploiter les données du site [http://www.prevision-meteo.ch](http://www.prevision-meteo.ch) pour tracer l'évolution horaire de la température à Strasbourg aujourd'hui.
Exploiter les données du site <https://www.prevision-meteo.ch> pour tracer l'évolution horaire de la température à Strasbourg aujourd'hui.

%% Cell type:markdown id: tags:
### Ouverture du fichier de prévisions
Le site [https://www.prevision-meteo.ch](https://www.prevision-meteo.ch) fournit des prévisions sous forme de fichier au format [json](https://fr.wikipedia.org/wiki/JavaScript_Object_Notation). On veut récupérer les données relatives à Strasbourg avec la méthode `urlopen()` du module `urllib.request`.
Le site <https://www.prevision-meteo.ch> fournit des prévisions sous forme de fichier au format [json](https://fr.wikipedia.org/wiki/JavaScript_Object_Notation). On veut récupérer les données relatives à Strasbourg avec la méthode `urlopen()` du module `urllib.request`.
print("Le téléchargement a échoué : on lit une version locale.")
f=open("exos/Strasbourg.json")
```
%% Cell type:markdown id: tags:
### Chargement du fichier json ouvert
%% Cell type:markdown id: tags:
La méthode `json.loads()` permet de charger un fichier json comme un dictionnaire python :
%% Cell type:code id: tags:
```
```python
importjson
jsondict=json.loads(f.read())# Read JSON file
```
%% Cell type:markdown id: tags:
### Exploration des données
On commence naïvement par afficher le contenu du fichier :
%% Cell type:code id: tags:
```
```python
print(type(jsondict))
print(jsondict)
```
%% Cell type:markdown id: tags:
On essaie de faire mieux en affichant uniquement les clés du dictionnaire :
%% Cell type:code id: tags:
```
```python
forkinjsondict:
print(repr(k))
```
%% Cell type:markdown id: tags:
On est intéressé par le temps d'aujourd'hui :
%% Cell type:code id: tags:
```
```python
day=jsondict['fcst_day_0']
print(day)
```
%% Cell type:markdown id: tags:
Là aussi, on cherche les clés :
%% Cell type:code id: tags:
```
```python
forkinday:
print(repr(k))
```
%% Cell type:markdown id: tags:
Vérifions qu'il s'agit d'aujourd'hui :
%% Cell type:code id: tags:
```
```python
print(day['day_long'],day['date'])
```
%% Cell type:markdown id: tags:
C'est bon !
Maintenant, une entrée particulière nous intéresse :
%% Cell type:code id: tags:
```
```python
day_hd=day['hourly_data']
forkinday_hd:
print(repr(k))
```
%% Cell type:markdown id: tags:
Regardons ce que contient une `hourly_data` :
%% Cell type:code id: tags:
```
```python
forkinday_hd['8H00']:
print(repr(k))
```
%% Cell type:markdown id: tags:
La clé qui nous intéresse est la chaîne `'TMP2m'` qui correspond à la température à 2m du sol.
%% Cell type:code id: tags:
```
```python
hour='12H00'
print(f"Aujourd'hui à {hour}, il fera : {day_hd[hour]['TMP2m']} deg. C.")
```
%% Cell type:markdown id: tags:
Sauver ces lignes de commandes dans le fichier `today_stras.py` en allant de l'exécution 1 au compteur d'exécution courant indiqué dans la cellule de code ci-dessus `In [XX]`. Dans le cas présent :
%% Cell type:code id: tags:
```
```python
# Décommenter la ligne ci-dessous
%save today_stras.py 1-12
%savetoday_stras.py1-10
```
%% Cell type:markdown id: tags:
### Tracé de la température
1. Ouvrir le fichier `today_stras.py` dans Spyder et nettoyer les `print` inutiles.
2. Exécutez le code dans Spyder et utilisez la fenêtre "Variable explorer" en haut à droite pour parcourir les données de votre dictionnaire.
3. Extraire la liste des couples `(hour, temperature)` où :
-`hour` est un entier
-`temperature` est un flottant
4. ordonner la liste selon les heures croissantes
5. convertir la liste en un *numpy array*`t` avec la méthode `numpy.array()`
6. Transposer `t` pour obtenir le tableau `[[array of hours], [array of temperatures]]`
7. réaliser un tracé matplotlib en suivant [ce tutoriel](http://matplotlib.org/users/pyplot_tutorial.html) ou en intégrant les lignes de code suivantes :
7. réaliser un tracé matplotlib en suivant [ce tutoriel](https://matplotlib.org/stable/tutorials/introductory/pyplot.html) ou en intégrant les lignes de code suivantes :
%% Cell type:code id: tags:
```
```python
importmatplotlib.pyplotasplt# To be placed at the top of python file
# ax = fig.add_subplot(111) # initialise a plot area
# fig.subplots_adjust(top=0.85)
# ax.set_title('Day temperature')
# ax.set_xlabel('Time [h]')
# ax.set_ylabel('Temperature [deg. C]')
#
# ax.plot(t[0], t[1]) # plot t[1] (tempe) as a function of t[0] (hour)
```
%% Cell type:markdown id: tags:
> **Option :** intégrer l'icone de la météo du jour en utilisant le module `matplotlib.image`.
%% Cell type:markdown id: tags:
Pas si vite ! Êtes-vous sûr ? Vraiment ?
Alors rendez-vous dans [exos/meteo_json.py](exos/meteo_json.py)
Alors rendez-vous dans [exos/correction/meteo_json.py](exos/correction/meteo_json.py)
%% Cell type:markdown id: tags:
## Exercice sur les fonctions
Modifiez le programme météo en créant une fonction qui admet un des jours disponibles comme argument (aujourd'hui, demain, après-demain...)
À partir de [`exos/correction/meteo_json.py`](exos/correction/meteo_json.py), écrivez le programme `meteo_json_func.py` qui contient une fonction `plot_day_tempe()` admettant deux arguments :
-`day_key` : un entier représentant le jour visé (`0`: aujourd'hui, `1`: demain, `2`: après-demain...)
-`city_name`: une chaîne de caractère de la ville recherchée
%% Cell type:code id: tags:
``` python
# Pour tester votre script dans cette cellule, décommenter les lignes suivantes
# et redémarrer le noyau avant chaque modification:
#from meteo_json_func import plot_day_tempe
#plot_day_tempe(2, city_name='Marseille')
```
%% Cell type:markdown id: tags:
Pas si vite ! Êtes-vous sûr ? Vraiment ?
Alors allez voir une proposition de solution dans [exos/meteo_json_func.py](exos/meteo_json_func.py)
Alors allez voir une proposition de solution dans [exos/correction/meteo_json_func.py](exos/correction/meteo_json_func.py)
[Jupyter ipywidgets](https://ipywidgets.readthedocs.io/en/latest/index.html) permet de créer très facilement des menus interactifs pour faciliter l'exécution de code dans les notebooks.