#!/usr/bin/env python
# -*- coding: utf-8 -*-
# # 1A.2 - Modules, fichiers, expressions régulières (correction)
#
# Correction.
# In[1]:
from jyquickhelper import add_notebook_menu
add_notebook_menu()
# In[2]:
get_ipython().run_line_magic('matplotlib', 'inline')
# ### Exercice 1 : Excel $\rightarrow$ Python $\rightarrow$ Excel
#
# Il faut télécharger le fichier [seance4_excel.xlsx](http://www.xavierdupre.fr/enseignement/complements/seance4_excel.xlsx) puis l'enregistrer au formet **texte (séparateur : tabulation) (*.txt)**. On rappelle les étapes de l'exercice :
#
# - enregistrer le fichier au format texte,
# - le lire sous python
# - créer une matrice carrée 3x3 où chaque valeur est dans sa case (X,Y),
# - enregistrer le résultat sous format texte,
# - le récupérer sous Excel.
# In[3]:
with open ("seance4_excel.txt", "r") as f :
mat = [ row.strip(' \n').split('\t') for row in f.readlines() ]
mat = mat [1:]
res = [ [ None ] * 3 for i in range(5) ]
for i,j,v in mat :
res [ int(j)-1 ] [ int (i)-1 ] = float(v)
with open ("seance4_excel_mat.txt", "w") as f :
f.write ( '\n'.join ( [ '\t'.join( [ str(x) for x in row ] ) for row in res ] ) )
# Il est très rare d'écrire ce genre de code. En règle générale, on se sert de modules déjà existant comme [pandas](http://pandas.pydata.org/), [xlrd](http://www.python-excel.org/) et [openpyxl](http://pythonhosted.org/openpyxl/). Cela évite la conversion au format texte :
# In[4]:
import pandas
df = pandas.read_excel("seance4_excel.xlsx", sheet_name="Feuil1", engine='openpyxl')
mat = df.pivot("X", "Y", "value")
mat.to_excel("seance4_excel_mat.xlsx")
mat
# C'est un peu plus rapide.
#
Exercice 2 : trouver un module (1)
#
# Le module [random](https://docs.python.org/3.4/library/random.html) est celui qu'on cherche.
# In[5]:
import random
alea = [ random.random() for i in range(10) ]
print (alea)
random.shuffle(alea)
print (alea)
# ### Exercice 3 : trouver un module (2)
#
# Le module [datetime](https://docs.python.org/3.4/library/datetime.html) permet de faire des opérations sur les dates.
# In[6]:
from datetime import datetime
date1 = datetime(2013,9,9)
date0 = datetime(2013,8,1)
print (date1 - date0)
birth = datetime (1975,8,11)
print (birth.weekday()) # lundi
# ### Exercice 4 : son propre module
#
# On effectue le remplacement ``if __name__ == "__main__":`` par ``if True :`` :
# In[7]:
# fichier monmodule2.py
import math
def fonction_cos_sequence(seq) :
return [ math.cos(x) for x in seq ]
if __name__ == "__main__" :
# et une petite astuce quand on travaille sous notebook
code = """
# -*- coding: utf-8 -*-
import math
def fonction_cos_sequence(seq) :
return [ math.cos(x) for x in seq ]
if True :
print ("Ce message n'apparaît que si ce programme est le point d'entrée.")
""".replace(" ","")
with open("monmodule3.py", "w", encoding="utf8") as f : f.write(code)
# In[8]:
import monmodule3
print ( monmodule3.fonction_cos_sequence ( [ 1, 2, 3 ] ) )
# Le message ``ce message n'apparaît que ce programme est le point d'entrée`` apparaît maintenant alors qu'il n'apparaissait pas avec la version de l'énoncé. Comme il apparaît après ``*``, cela montre que cette ligne est exécutée si le module est importé.
# In[9]:
import monmodule3
# Si on importe le module une seconde fois, le message n'apparaît plus : le langage Python a détecté que le module avait déjà été importé. Il ne le fait pas une seconde fois.
# ### Exercice 5 : chercher un motif dans un texte
#
# L'expression régulière est ``je .{1,60}``. Le symbol ``.`` signifie n'importe quel caractère. Suivi de ``{1,60}`` veut dire n'importe quel caractère répété entre 1 et 60 fois.
# In[10]:
import pyensae.datasource, re
discours = pyensae.datasource.download_data('voeux.zip', website = 'xd')
exp = re.compile ("je .{1,60}", re.IGNORECASE)
for fichier in discours :
print("----",fichier)
try:
with open(fichier,"r") as f : text = f.read()
except:
with open(fichier,"r", encoding="latin-1") as f : text = f.read()
je = exp.findall(text)
for t in je :
print (t)
# ### Exercice 6 : chercher un autre motif dans un texte
#
# Pour les mots _securite_ ou _insecurite_, on construit l'expression :
# In[11]:
import pyensae.datasource, re
discours = pyensae.datasource.download_data('voeux.zip', website = 'xd')
exp = re.compile ("(.{1,15}(in)?sécurité.{1,50})", re.IGNORECASE)
for fichier in discours :
print("----",fichier)
try:
with open(fichier,"r") as f : text = f.read()
except:
with open(fichier,"r", encoding="latin-1") as f : text = f.read()
je = exp.findall(text)
for t in je :
print (t)
# ## Exercice 7 : recherche les urls dans une page wikipédia
#
# On pourra prendre comme exemple la page du programme [Python](https://fr.wikipedia.org/wiki/Python_(langage)). La première partie consiste à récupérer le contenu d'une page HTML.
# In[12]:
from urllib.request import urlopen
url = "https://fr.wikipedia.org/wiki/Python_(langage)"
with urlopen(url) as u:
content = u.read()
content[:300]
# Les données récupérées sont au format binaire d'où le préfixe ``b''``. Pour éviter de télécharger les données à chaque fois, on sauve le contenu sur disque pour le récupérer la prochaine fois.
# In[13]:
with open('page.html', 'wb') as f:
f.write(content)
# Et on le recharge.
# In[14]:
with open('page.html', 'rb') as f:
page = f.read()
page[:300]
# Les données sont sous forme d'octets, il faut d'abord les convertir sous forme de caractères. il y a plus de caractères que d'octets disponibles (256), c'est cela qu'il faut une sorte de code pour passer de l'un à l'autre : dans le cas d'internet, le plus utilisé est l'[encoding utf-8](https://fr.wikipedia.org/wiki/UTF-8).
# In[15]:
page_str = page.decode('utf-8')
page_str[:300]
# On recherche maintenant les urls commençant par http...
# In[16]:
import re
reg = re.compile("href=\\\"(http.*?)\\\"")
urls = reg.findall(page_str)
urls[:10]
# ## Exercice 8 : construire un texte à motif
#
# A l'inverse des expressions régulières, des modules comme [Mako](http://www.makotemplates.org/) ou [Jinja2](http://jinja.pocoo.org/docs/dev/) permettent de construire simplement des documents qui suivent des règles. Ces outils sont très utilisés pour la construction de page web. On appelle cela faire du [templating](https://wiki.python.org/moin/Templating). Créer une page web qui affiche à l'aide d'un des modules la liste des dimanches de cette année.
# In[17]:
patron = """
{% for i, url in enumerate(urls) %}
- url {{ i }}
{% endfor %}
"""
# In[18]:
from jinja2 import Template
tpl = Template(patron)
# In[19]:
print(tpl.render(urls=urls[:10], enumerate=enumerate))
# In[20]: