Python

Scraper le web avec Selenium en Python

Contexte : je suis sous MacOS en architecture Intel 64bit (processeur Core i5)

Selenium vous permet programmatiquement d’émuler un navigateur (ici ce sera Chrome), et de télécharge une page et de l’analyser. Pourquoi est ce que c’estintéressant? Pour les test d’interface d’une part, puis d’autre part si vous voulez scraper une page très javascript, où les éléments sont rendus en JS donc non récupérables par un scrap avec BeautifulSoup, Selenium le peut.

Il est juste plus lent que BeautifulSoup, en effet il se repose sur le navigateur Chrome (notre cas ici mais ça peut être n’importe quel navigateur) qui fait le rendu, alors que BeautifulSoup ne fait pas le rendu.

Pré-requis :

  • connaissez votre version de navigateur Chrome, en allant dans les 3 petits point puis Aide puis A Propos de Google Chrome
  • Déterminez l’architecture de votre plateforme
  • Ensuite allez sur le site de Chromium pour télécharger le chromedriver à mettre dans le même répertoire que votre script, le driver permet à Selenium de contrôler Chrome, c’est dépendant de l’OS et du microprocesseur. Il faut suivre le lien pour les dernières versions de Chrome Vous trouverez aussi les zip de Chrome for testing, que Selenium va lancer. chromedriver et Chrome for Testing doivent être téléchargés ensemble.
  • Installer la librairie Selenium pip install selenium

Script minimal de Selenium pour scraper une page

from selenium import webdriver
from selenium.webdriver.common.keys import Keys

browser = webdriver.Chrome()   #mac https://stackoverflow.com/questions/76928765/attributeerror-str-object-has-no-attribute-capabilities-in-selenium
#driver = webdriver.Chrome('./chromedriver'). #ne marche pas sur Mac

browser.get("https://www.python.org")

print(browser.title)

Mettre en place un environnement Python dans VSCode

CTRL + SHIFT + P puis Python: Create Environment et sélectionnez la commande.

Choisissez l’interpréteur

Ensuite ça prend un peu de temps pour créer l’espace virtuel, isolé de développement Python.

Pour s’assurer de la version de l’interpréteur Python, dans la palette de commande (CTRL + SHIFT + P) puis Python: Select Interpreter

Maintenant vous êtes prêt pour commencer à coder en Python dans VSCode.

Créez un fichier hello.py,

print("hello")

Pour exécuter, appuyez sur le triangle en haut à droite de VSCode, liste déroulante choisir Debug Python File. Notez le point rouge qui est le point d’arrêt.

Debugger python sous VScode

Il suffit de mettre un point d’arrêt et de cliquer sur le symbole debug dans la barre latérale. Une autre méthode est d’utiliser le menu contextuel et démarrer le script.

Pour plus d’information ce lien.

Comment télécharger une vidéo Wistia avec le langage Python

La plateforme Wistia est un hébergeur de vidéo, souvent utilisé dans les sites en accès restreint (pour la formation par exemple). Parfois on a envie de télécharger les vidéo pour regarder plus tranquillement quan on est en vacances dans un endroit où l’internet n’est pas très développé. Il vous faut télécharger les vidéos.

Nous allons voir comment on peut le faire ne Python. Pour ce faire vous devez avoir installé un environnement python et avoir déjà manipulé ce langage.

Le dépôt du projet Wisty : https://pypi.org/project/wisty/

Télécharger la librairie Wisty

pip install wisty

Extraire l’identifiant de la vidéo

sur la vidéo, faites un clic droit, ou deux clic droit pour faire apparaitre la popup qui vous permet de copier le code HTML d’intégration de la vidéo. Collez ce code dans un éditeur de texte, copiez la portion qui est juste après l’url de la page

<a href="https://www.lesite.com?wvideo=nts3yvnjlb">

Ici c’est nts3yvnjlb, nous allons avoir beosin de cet identifiant dans la commande en ligne

Ecrire la ligne de commande qui permet de télécharger la vidéo

Si vous utilisez le terminal de Pycharm, dans le projet ou le venv dans lequel vous avez installé Wisty, vous pouvez directement taper cette commande:

wisty -i nts3yvnjlb-r 720p -n nom-fichier-en-local

Si vous voulez faire la même chose depuis un prompt DOS :

C:\Users\admin\PycharmProjects\pythonProject\venv\Scripts\wisty -i nts3yvnjlb-r 720p -n nom-fichier-en-local

Assurez vous que le nom du projet (pythonProject) est bien celui où vous avez installé la librairie.

Comment économiser de l’espace mémoire

Le paramère 720p concerne la résolution de la vidéo que vous téléchargez, la définition 1080p est vraiment dix fois plus lourde que la 720p, qui reste pour certains types de vidéo de très bonne qualité.

Optimiser vos téléchargement avec un script batch sous Windows

Par exemple sur Windows vous pouvez créer un fichier .bat et y mettre les multiple commandes de téléchargements de vidéo. Mettez de préférence les commandes avec le chemin absolu, une comande par ligne, ensuite il ne vous reste plus qu’à lancer le fichier .bat pour télécharger tranquillement vos vidéos.

Utiliser un socket en Python pour lire les cours sur Binance

A quoi servent les sockets?

Les sockets vous permettent d’ouvrir une liaison continue entre le serveur et le client. A la différence d’une requête AJAX, qui est l’équivalent d’un chargement de page HTTP, qui s’arrête une fois les informations téléchargées, le socket ouvre un stream continu. Cela évite les limitations des requêtes AJAX, comme par exemple la limitation du nombre de requêtes par minutes par exemple.

Si vous voulez connaitre un cours de bourse en temps réel, hors de question d’utiliser des requêtes AJAX, car vous allez vous faire blacklister.

Installer la librairie websocket-client

Il vous faut installer la librairie websocket-client (attention il y a une autre librairie qui s’appelle websocket, ce n’est pas celle là)

pip install websocket-client

Le script:

import websocket,json,os
def on_message(ws, message):
    """ convert string to dictionary"""
    message = json.loads(message)
    clear = lambda: os.system('cls')
    clear()
    print(message)
    print(" ",message['data'][0]['p'],flush=True,end="\r")


def on_error(ws, error):
    print(error)

def on_close(ws, close_status_code, close_msg):
    print("### closed ###")

def on_open(ws):
    ws.send('{"method":"SUBSCRIBE","params":["btcusdt@aggTrade","btcusdt@depth"],"id":1}')

if __name__ == "__main__":
    websocket.enableTrace(False)
    ws = websocket.WebSocketApp(f"wss://stream.binance.com:9443/ws/bnbbtcopen@depth",
                              on_open=on_open,
                              on_message=on_message,
                              on_error=on_error,
                              on_close=on_close)
    ws.on_open = on_open
    ws.run_forever()

Lien vers la documentation du service websocket de Binance:

Python Module not found en exécution en ligne de commande

Alors que ça marchait très bien sous PyCharm…

Imaginons que vous ayez un programme utilisant une librairie externe, par exemple Beautifulsoup, ce dernier étant une librairie externe, donc il faut l’importer avec la commande :

pip install beautifulsoup4

Sous PyCharm, la librairie sera installée dans la section External Librairies, dans la barre latérale Project. Mais le véritable répertoire (sous Windows) sera :

C:\Users\mon_user\PycharmProjects\nom_projet\venv\Lib\site-packages

Remplacez mon_user et nom_projet par vos données propres.

Ainsi lorsque vous exécutez un programme en ligne de commande, et qu’il vous dit « Module Not Found …bs4 » c’est que l’exécutable Python n’arrive pas à le trouver. Il faut créer la variable PYTHONPATH.

Pour ce faire (Windows) dans la boite de recherche de Windows (Cortana) tapez PATH, vous accédez aux variables d’environnement. Ajoutez la nouvelle variable PYTHONPATH puis ajoutez le chemin cité plus haut. MAintenant vous pouvez lancer votre programme en ligne de commande.

Lister les valeurs des chemins d’inclusion

import sys
print(sys.path)

Ce programme va vous afficher tous les chemins qui sont tenus compte pour la recherche de module. En fonction de votre environnement virtuel, les résultats peuvent différer, et vous saurez pourquoi vous avez un Module Not Found.

Python : nombre d’argument arbitraire avec **kwargs et *args

En python il est possible de construire des fonctions qui acceptent un nombre indéfini de paramètres, aussi bien en positionnel qu’en nommé.

*args

def mafonction(*args):
   for a in args:
        print(a)

mafonction(1)
# 1
mafonction(1,2,3)
# 1
# 2
# 3

le *args est interprété comme un tuple

**kwargs

def mafonction(param,*args,**kwargs):
    for a in kwargs:
        print(a,kwargs[a])

mafonction(nom="Dupont",age=27)
#nom Dupont
#age 27

Notez qu’il n’est pas nécessaire de les appeler *args et **kwargs, on peut utiliser d’autres noms.

On peut mixer ces deux types de paramètre avec des paramètres classiques

def mafonction(param1,*args,**kwargs):
    

Unpack argument list

Cette technique consiste à préfixer le paramètre d’un astérisque, pas lors de la déclaration de la fonction, mais lors de l’appel de la fonction.

def mafonction(a,b,c):
    print(a,b,c)

obj = {"nom":"Dupont","age":27}
mafonction(100,**obj)
# 100,Dupont 27

def mafonction(a,b):
    print(a,b)

l = [1,2]
mafonction(*l)
# 1 2

Pour les listes et tuple on utilisera *args, pour les dictionnaire on utilisera **

mylist = [1,2,3]
>>> foo(*mylist)
x=1
y=2
z=3

>>> mydict = {'x':1,'y':2,'z':3}
>>> foo(**mydict)
x=1
y=2
z=3

>>> mytuple = (1, 2, 3)
>>> foo(*mytuple)
x=1
y=2
z=3

Extended iterable unpacking

Une façon de faire de l’unpacking puissante

first, *rest = [1,2,3,4]
first,*l,last = [1,2,3,4]

Enfin un esyntaxe propre à Python 3 :

def mafonction(arg1,arg2,*,kwarg1,kwarg2):
    pass

La syntaxe ci-dessus impose que les deux premiers paramètres soient positionnel, et les paramètre après l’astérisque soient nommés.

https://stackoverflow.com/questions/36901/what-does-double-star-asterisk-and-star-asterisk-do-for-parameters

Python : tester si une variable est un nombre avec isdigit ()

Le problème de conversion d’une chaine en nombre entier

Lorsqu’on a une chaine de caractères qu’on cherche à convertir en nombre, il faut se poser la question de si c’est faisable.

Imaginons qu’on ait une variable à tester dont le type est un string :

ns = "125"
n = int(ns)

Mais si on a une chaine de caractère qui ne contient pas purement des chiffres (voire une chaine vide):

nm1 = "12.3"
nm2 = "z123"
nm3 = ""

Tenter de convertir ces chaines en entier déclenchera une erreur de type ValueError.

Tester si une chaine est un nombre entier avec isdigit()

En Python tout est objet, un nombre entier est un objet, un booléen est un objet, un float est un objet,(vous pouvez le voir en utilisant la notation pointée). Ces objets ont des méthodes (c’est le nom en OOP pour une fonction). Et dans le cas des chaines de caractères, uen de ces méthode est isdigit().

n = "123"
print(n.isdigit())  # True 
n = ""
print(n.isdigit())   # False
#on peut encore écrire
print("123".isdigit())  #True

Ainsi avant de convertir en entier, testez la chaine avec isdigit() avant d’utiliser int()

if("123".isdigit()):
    n = int("123")

Connexion à MySQL en Python

Installez au préalable Mysql, le plus rapide (avec zéro configuration ) étant d’installer la solution de développement PHP Laragon si vous êtes sous windows.

Ensuite il faudra redéfinir le mot de passe root, allez dans Laragon click droit sur le bouton Database > Mysql > Change root password.

Connexion à Mysql en Python

from mysql.connector import MySQLConnection, Error

def connect():
    """ Connect to MySQL database """
    conn = None
    try:
        conn = mysql.connector.connect(host='localhost',
                                       database='boutique',
                                       user='root',
                                       password='root')
        if conn.is_connected():
            print('Connected to MySQL database')

    except Error as e:
        print(e)

    finally:
        if conn is not None and conn.is_connected():
            conn.close()

if __name__ == '__main__':
    connect()

Exécuter une requête SQL en Python

from mysql.connector import MySQLConnection, Error

def query_with_fetchone():
    try:

        conn = MySQLConnection(host='localhost',
                                         database='boutique',
                                         user='root',
                                         password='root')
        cursor = conn.cursor()
        cursor.execute("SELECT * FROM staffs")

        row = cursor.fetchone()

        while row is not None:
            print(row)
            row = cursor.fetchone()

    except Error as e:
        print(e)

    finally:
        cursor.close()
        conn.close()


query_with_fetchone()

Connexion à Sqlite en Python

Sqlite est une base de donnée un peu spéciale, puisque la base tient dans un fichier binaire, avec extension .db, c’est donc quelque chose de très simple, et Sqlite est destiné à être utilisé sur des systèmes embarqués.

Donc pas besoin d’installer un programme, c’est la librairie Python qui va s’ocuper de cela. De plus c’est dans la librairie standard, ce qui veut dire que l’on n’ pas besoin de faire un pip install.

La librairie Python sqlite3

Il suffit tout simplement d’importer la librairie sqlite3, de créer une connexion pour créer le fichier binaire de la base de données

import sqlite3
from sqlite3 import Error


def create_connection(db_file):
    """ crée une connexion SQLite si lea DB n'existe pas elle sera créée"""
    conn = None
    try:
        conn = sqlite3.connect(db_file)
        print(sqlite3.version)
    except Error as e:
        print(e)
    finally:
        if conn:
            conn.close()


if __name__ == '__main__':
    create_connection(r"C:\db\pythonsqlite.db")

Sivous exécutez pour la première fois ce script, le fichier pythonslqite.db sera créé, par contre il vous faudra avoir le répertoire déjà créé, sinon vous aurez une erreur. Vous pouvez aussi créer une base de données avec DB Browser, un browser de base sqlite.

Requêter dans Sqlite en Python

Voici la recette pour faire une requête SQL en Python dans Sqlite. On acréé la base de données test.db, et il y a une table items. Vous pouvez importer dans DBBrowser le fichier contenant les données ci-dessous ou exécuter le SQL suivant :

BEGIN TRANSACTION;
CREATE TABLE IF NOT EXISTS "items" (
	"id"	INTEGER,
	"nom"	TEXT,
	"prix"	INTEGER
);
INSERT INTO "items" VALUES (1,'Pomme',5);
INSERT INTO "items" VALUES (1,'Poire',3);
INSERT INTO "items" VALUES (1,'raisin',13);
COMMIT;
import sqlite3
from sqlite3 import Error

def create_connection(db_file):
    conn = None
    try:
        conn = sqlite3.connect(db_file)
    except Error as e:
        print(e)

    return conn

def select_items(conn):
    """
    Query all rows in the tasks table
    :param conn: the Connection object
    :return:
    """
    cur = conn.cursor()
    cur.execute("SELECT * FROM items")

    rows = cur.fetchall()

    for row in rows:
        print(row)

db_file = "c:\\Users\\admin\\Documents\\test.db"
conn = create_connection(db_file)
select_items(conn)

Compréhension de liste en Python

Base de compréhension de liste

list = [i for i in range(5)]
print(list)  # [0,1,2,3,4]
list2 = [ i * i for i in range(10)]
print(list2) # [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

If dans compréhension de liste

list3 = [ n for n in range(10) if n % 2 == 0]
print(list3) # [0, 2, 4, 6, 8]

If imbriqués
list4 = [ n for n in range(10) if n % 2 == 0 if n >= 5]
print(list4) # [6, 8]

If…Else dans compréhension de liste

list5 = ["Even" if i%2==0 else "Odd" for i in range(10)]
print(list5) #

list6 = [str(i) + ":Pair" if i%2==0 else str(i) + ":Impair" for i in range(10)]
print(list6) 
# ['0:Pair', '1:Impair', '2:Pair', '3:Impair', '4:Pair', '5:Impair', '6:Pair', '7:Impair', '8:Pair', '9:Impair']

Attribut de classe et d’instance en Python

Attribut de classe

class Dog:
    leg_number = 4
    def __init__(self,name):
        self.name = name

chien1 = Dog("Médor")
print(chien1.leg_number)  # 4
print(Dog.leg_number)     # 4

Dans l’exemple ci-dessus leg_number est un attribut de classe. Pyton va chercher d’abord dans les attribut d’instance pour voir si leg_number existe, sinon va aller chercher dans les attributs de classe.

Attribut d’instance

name est un attribut d’instance car rattaché à self.

class Dog:
    leg_number = 4
    def __init__(self,name):
        self.name = name

chien1 = Dog("Médor")
print(chien1.name)  # Médor
print(Dog.name)     # AttributeError: type object 'Dog' has no attribute 'name'

Python ne trouvera pas name en attribut de classe. Par contre on peut surcharger name en attribut de classe.

class Dog:
    leg_number = 4
    name = "toto"
    def __init__(self,name):
        self.name = name

chien1 = Dog('médor')
print(chien1.name)   # médor
print(Dog.name)      # toto

Un attribut de classe est commun à tous les objets qui en dérivent.

class Dog:
    leg_number = 4
    def __init__(self,name):
        self.name = name

chien1 = Dog('médor')
chien2 = Dog('Lassie')
print(chien1.leg_number)
print(chien2.leg_number)
Dog.leg_number = 5
print(chien1.leg_number)
print(chien2.leg_number)

https://www.toptal.com/python/python-class-attributes-an-overly-thorough-guide

Héritage de classe dans Python

A première vue, les notions d’orienté objet sont simple en Python par rapport à Java, mais même si l’encapsulation ,n’existe pas en tant que tel (voir le mangling en Python), il y a beaucoup de choses à apprendre en héritage dans Python.

Il y a les fonctions magiques (avec le dunder) pour faire du polymorphisme et l’héritage multiple comme en C++ !

Classe et héritage simple

class Kite:
    def __init__(self,max_altitude):
        self.max_altitude = max_altitude
    def do(self):
        return "I fly"
    def getMaxAltitude(self):
        return self.max_altitude


class BigKite(Kite):
    def __init__(self,max_altitude,weight):
        self.max_altitude = max_altitude
        self.weight = weight
    def getWeight(self):
        return self.weight

Ici BigKite hérite de Kite, et la méthode de constructeur __init__ est surchargée. Si nous voulons utiliser le constructeur de la classe parente :

class Kite:
    def __init__(self,max_altitude):
        self.max_altitude = max_altitude
    def do(self):
        return "I fly"
    def getMaxAltitude(self):
        return self.max_altitude


class BigKite(Kite):
    def __init__(self,max_altitude,weight):
        super().__init__(max_altitude) #appel classe parente
        self.weight = weight
    def getWeight(self):
        return self.weight

On aurait pu écrire aussi :

super(Kite,self).__init__(max_altitude)

Héritage multiple

Ici KiteSurf hérite de la classe Kite et de la classe Surf, qui elles-même héritent de Object, on est ici en présence de diamond problem

class Object:
    def __init__(self):
        pass
    def do(self):
        return "I exist"


class Kite(Object):
    def __init__(self,max_altitude):
        self.max_altitude = max_altitude
    def do(self):
        return "I fly"
    def getMaxAltitude(self):
        return self.max_altitude


class Surf(Object):
    def __init__(self,matter):
        self.matter = matter
    def do(self):
        return "I surf"
    def getMaxAltitude(self):
        return self.max_altitude

class KiteSurf(Surf,Kite):
    def __init__(self):
        pass

ks = KiteSurf()
print(ks.do())

L’affichage de ks.do() méthode existant dans Kite et dans Surf dépend de l’ordre dans lequel est passé en paramètre les classes parentes.

https://he-arc.github.io/livre-python/super/index.html

Encapsulation dans les classes Python

Il n’existe pas de private ni de protected dans Python, la philosophie de Python est que le développeur est un être responsable.

Cependant Python supporte ce que l’on appelle le mangling.

class Dog:
    __init__(self):
        self.name = "Médor"
        self.__tatoo = "X312B13"

chien1 = Dog()
print(chien1.name) # Médor
print(chien1.__tatoo) # AttributeError: 'Dog' object has no attribute '__tatoo'

__tatoo a été substitué par un autre nom en vertu des deux underscores, on ne connait pas le nouveau nom, ce qui reproduit le process d’encapsulation.

Mécanisme de session de Django

Similaire aux sessions en PHP, dans Django il faut importer deux lignes pour pouvoir travailler avec les sessions:

#settings
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions', // le module Session
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'products.apps.ProductsConfig'
]

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware', // le middleware
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

Avec Django par défaut les sessions sont sauvées dans la base de données.

Les formulaires dans Django

Les formulaires sont un vaste chapitre comme dans tout framework web quelque soit le langage. Mais Django permet de les manipuler plus facilement que Symfony par exemple.

cleaned_data qu’est ce que c’est?

Il y a deux types de formulaire dans Django, les formulaires classiques qui héritent de forms.Form, et mes formulaires liés à des entités, qui héritent de forms.ModelForm.

Avec les modelForm, inutile de s’inquiéter du cleaned_data.

Dans un form classique on doit utiliser les données validée:
if form.is_valid():
    ex = Example()
    ex.username = form.cleaned_data['username']
    ex.save()

Alors que dans un modelForm, cette étape est automatique.

if form.is_valid():
    form.save()

https://stackoverflow.com/questions/53594745/what-is-the-use-of-cleaned-data-in-django

Upload de fichiers dans Django

Pour uploader un fichier dans un formulaire, il faut modifier le model,

class Product(models.Model):
    name = models.CharField(max_length=50)
    price = models.FloatField()
    stock = models.IntegerField()
    image = models.CharfieldField(max_length=1000)

class Product(models.Model):
    name = models.CharField(max_length=50)
    price = models.FloatField()
    stock = models.IntegerField()
    image = models.FileField()

Après avoir changé la propriété dans le model, il faut faire une migration

python manage.py makemigrations products  #le nom de l'app
python manage.py migrate

Ensuite il faut faire quelques modification de code, dans le settings.py de votre projet :

#monprojet\settings.py
MEDIA_ROOT = os.path.join(BASE_DIR,'media')
MEDIA_URL = '/media/'

#monprojet\urls.py
from django.contrib import admin
from django.urls import path, include

from django.conf import settings
from django.conf.urls.static import static

urlpatterns = [
    path('admin/', admin.site.urls),
    path('products/', include('products.urls'))
]

if settings.DEBUG:
    urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
    urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

Introduction à Jupyter Notebook

Jupyter Notebook est une interface web pour faire de la datascience, vous exécutez vos scnippet Python dans ce qu’on appelle des cells, des unités d’exécution.

Pour l’installer, voici la procédure :

Installation des librairies

pip install pandas
pip install numpy
pip install matplotlib
pip install xlrd

Installation de Jupyter Notebook

pip install notebook

#démarrer notebook
jupyter notebook

Vous pouvez installer d’abord Jupyter Notebook et installer les librairies depuis Jupyter Notebook

!pip install pandas 

le ! permet d'accéder au shell.

Afficher les log server dans Python Django

Il est pratique de logger en mode développement les requêtes servies par le serveur de Python

dans le fichier settings.py de votre projet mettez ce code juste après le DEBUG = true

if DEBUG:
    # will output to your console
    logging.basicConfig(
        level = logging.DEBUG,
        format = '%(asctime)s %(levelname)s %(message)s',
    )
else:
    # will output to logging file
    logging.basicConfig(
        level = logging.DEBUG,
        format = '%(asctime)s %(levelname)s %(message)s',
        filename = '/my_log_file.log',
        filemode = 'a'
    )

https://stackoverflow.com/questions/4558879/python-django-log-to-console-under-runserver-log-to-file-under-apache

Comprendre le mot clé with en Python

La syntaxe en Python de with est assez étrange, quel problème essait-il de résoudre?

with est utilisé lorsqu’on travaille avec des ressources non managées, notamment ouverture d’une fichier. Avant on utilisait try...catch,

    set things up
    try:
        do something
    finally:
        tear things down

Syntaxe basique de with

with expression [as variable]:
    with-block

L’expression est évaluée, et retourne un objet qui implémente le context management protocol, c’est à dire qui possède les méthodes __enter__() et __exit__()

with open('text.txt','w') as fichier
    fichier.write('Hello')

Avec cette syntaxe pas besoin de fermer explicitement le fichier, c’est automatique.

Introduction à Numpy

Numpy est une librairie Python qui introduit une nouvelle structure de données l’Array, qui est comme une liste, mais en beaucoup plus rapide.

Installation de Numpy

pip install numpy
#test.py
import numpy
arr = numpy.array([1,2,3,4,5])
print(arr)

Importation de Numpy avec un alias

import numpy as np
arr = np.array([1,2,3,4,5])
print(np.__version__)

Array scalaire 0 dimension

import numpy as np
arr = np.array(42)
print(arr) 

Array unidimensionnel

import numpy as np
arr = np.array([1, 2, 3, 4, 5])
print(arr) 

Array 2D

import numpy as np
arr = np.array([[1, 2, 3], [4, 5, 6]])
print(arr) 

Dans le cas particuliers des matrices Numpy a une librairie dédiée numpy.mat

Array 3D utilisé pour représenter les tenseurs.

Checker la dimension d’un array avec ndim

import numpy as np
arr = np.array([[1, 2, 3], [4, 5, 6]])
print(arr.ndim) 

Index des array c’est comme les listes

Le notation est différente ce ce qu’on peut voir en Javascript

import numpy as np
arr = np.array([[1,2,3,4,5], [6,7,8,9,10]])
print('2nd element on 1st dim: ', arr[0, 1]) 

Index négatif

pour accéder depuis la fin

import numpy as np
arr = np.array([[1,2,3,4,5], [6,7,8,9,10]])
print('Last element from 2nd dim: ', arr[1, -1]) 

Array slicing

import numpy as np
arr = np.array([1, 2, 3, 4, 5, 6, 7])
print(arr[1:5]) 
print(arr[4:]) 
print(arr[:4]) 
print(arr[:]) 
print(arr[-3:-1]) #Array slicing négatif
print(arr[1:5:2]) #step slicing !cette notation exclut le dernier (tem index 5 n'est pas pris en compte)

Slicing 2D array

import numpy as np
arr = np.array([[1, 2, 3, 4, 5], [6, 7, 8, 9, 10]])
print(arr[1, 1:4])  # sur un array
print(arr[0:2, 2]) # sur deux array
print(arr[0:2, 1:4]) # sur deux array de 1 à 4

Les datatype de Numpy


		

Insérer un modèle dans la base avec Django

De la même façon qu’on peut générer un formulaire facilement avec le modèle, on peut facilement insérer dans la base de données une entité provenant d’un formulaire HTML généré de cette façon, ou en le construisant from scratch depuis une méthode de view

#models.py
class Foo(models.Model):
    name = models.CharField(max_length=100)

#view.py
def add(request):
    foo_instance = Foo.objects.create(name='test')
    return render(request, 'some_name.html.html')

Ou l’on peut se servir du model directement

from django.http import HttpResponse
from django.template import loader

from .models import Article


def index(request):
    article = Article()
    article.title = 'This is the title'
    article.contents = 'This is the content'
    article.save()

    template = loader.get_template('articles/index.html')
    context = {
        'new_article_id': article.pk,
    }
    return HttpResponse(template.render(context, request))

En utilisant les model form c’et plus simple

# views.py
def monform(request):
    if request.method == 'POST':
        # create a form instance and populate it with data from the request:
        form = MyProductForm(request.POST)
        if form.is_valid():
            form.save()
            return HttpResponseRedirect('/products/thanks')

    # if a GET (or any other method) we'll create a blank form
    else:
        form = MyProductForm()

    return render(request, 'myproductform.html', {'form': form})

#form.py
class MyProductForm(ModelForm):
    class Meta:
        model = Product
        fields = ['name', 'price', 'stock', 'image']  #or use tuple
#models.py
class Product(models.Model):
    name = models.CharField(max_length=50)
    price = models.FloatField()
    stock = models.IntegerField()
    image = models.CharField(max_length=2000)
Retour en haut