====== Python ======
* [[python:gunicorn|Gunicorn]]
* [[:git-python-api|API de GitHub, Gitlab, ...]]
* [[filesystem|Manipulation du système de fichiers]]
* [[math-snippets|Snippets de fonctions mathématiques]]
* [[pymysql|PyMySQL]]
* [[graphviz|API de GraphViz]]
* [[python:images|Manipulation d'images]]
* [[python:modules|Gestion des modules]]
* [[python:http-request|Requêtes HTTP]]
* [[python:pickle|Pickle]]
* [[python:tests|Tests unitaires]]
* [[python:packaging|Packaging des modules Python]]
* [[https://python-guide-pt-br.readthedocs.io/fr/latest/#__do_not_save__|Le guide de l’auto-stoppeur pour Python!]]
* [[https://gist.github.com/sloria/7001839|The Best of the Best Practices (BOBP) Guide for Python]]
* [[https://www.thecodeship.com/patterns/guide-to-python-function-decorators/|A guide to Python's function decorators]]
* [[https://www.nicholashairs.com/posts/major-changes-between-python-versions/|Summary of Major Changes Between Python Versions]]
* [[https://stackoverflow.com/questions/31375656/how-to-draw-the-paths-of-a-networkx-graph-using-different-colours]]
==== Environnements virtuels ====
[[https://docs.python.org/3/tutorial/venv.html|Source]]
=== Créer un environnement ===
python3 -m venv new-env
''new-env'' est le nom du dossier qui va contenir le nouvel environnement virtuel.
=== Activer l'environnement ===
Dans le dossier de l'environnement:
source bin/activate
==== Yaml ====
https://pyyaml.org/
=== Installation ===
sudo pip3 install pyyaml
=== Lecture d'un fichier YAML ===
import yaml
config_file = open("file.yaml", 'r')
config = yaml.safe_load(config_file)
''config'' est alors un dictionnaire contenant toutes les clés du fichier Yaml.
Voir [[https://github.com/yaml/pyyaml/wiki/PyYAML-yaml.load(input)-Deprecation|la note]] sur le dépôt pour les différents //loaders//.
=== Écriture d'un fichier YAML ===
import yaml
vars_dict = dict()
# ...
with open('file.yaml'), 'w') as yaml_file:
yaml.dump(vars_dict, yaml_file, default_flow_style=False)
==== Arguments du programme ====
import sys
if len(sys.argv) < 2:
sys.exit(1)
action = sys.argv[1]
==== argparse ====
* https://docs.python.org/3/library/argparse.html
Permet de gérer facilement les arguments passés à un script, et générer la documentation qui va avec.
import argparse
cli_parser = argparse.ArgumentParser()
cli_parser.add_argument("config_file", help="Configuration file in YAML format")
cli_parser.add_argument("nb_cores_per_numa", help="Number of cores per NUMA node", type=int)
args = cli_parser.parse_args()
''args'' est un objet contenant les paramètres passés en arguments du script (par exemple: ''args.config_file'').
Pour avoir un paramètre optionnel avec une valeur par défaut :
cli_parser.add_argument("b", help="Block size", type=int, nargs="?", default=320)
==== Fonction par défaut ====
if __name__ == '__main__':
# some stuff
==== Lire un fichier ====
[[https://www.pythonforbeginners.com/files/reading-and-writing-files-in-python|Source]]
with open(filename, 'r') as file:
content = file.read()
# ou
lines = file.readlines() # liste où chaque élément est une ligne du fichier
# ou
for line in file:
print(line)
# ou
print(file.readline(3)) # lit la 3ème ligne du fichier
Pour préciser l'encodage du fichier ([[http://sametmax.com/lencoding-en-python-une-bonne-fois-pour-toute/|Source]]):
with open(filename, 'rb') as file:
content = file.read().decode('windows-1252')
=== CSV ===
[[https://docs.python.org/fr/3/library/csv.html]]
import csv
with open('eggs.csv', newline='') as csvfile:
spamreader = csv.reader(csvfile, delimiter=' ', quotechar='|')
nb_lines = sum(1 for row in spamreader)
for row in spamreader:
print(', '.join(row))
Écrire un CSV:
import csv
someiterable = [
['abc', 20.7, 17.2],
['def', 20.6, 17.1]
]
with open('some.csv', 'w', newline='') as f: # possibilité d'utiliser le mode 'a' pour ajouter à la fin d'un fichier existant. Dans tous les cas, le fichier sera créé s'il n'existe pas.
writer = csv.writer(f)
writer.writerows(someiterable)
Il est possible d'écrire sur la sortie standard en utilisant le fichier ''sys.stdout''.
=== Ignorer la première ligne ===
reader = csv.reader(file)
next(reader)
=== Lire l'entrée standard ou un fichier ===
[[https://stackoverflow.com/questions/1450393/how-do-i-read-from-stdin|Source]]
import sys
f = open(sys.argv[1]) if len(sys.argv) == 2 else sys.stdin
# ... work with f ...
if len(sys.argv) == 2:
f.close()
==== Ecrire sur stderr ====
* [[https://eli.thegreenplace.net/2015/redirecting-all-kinds-of-stdout-in-python/|Redirecting all kinds of stdout in Python]]
import sys
print("Erreur", file=sys.stderr)
==== Listes ====
=== Retirer un élément ===
Récupère et retire l'élément d'index passé en paramètre:
e = liste.pop(0)
=== Index d'un élément d'une liste ===
[[https://www.programiz.com/python-programming/methods/list/index]]
vowels = ['a', 'e', 'i', 'o', 'i', 'u']
index = vowels.index('e')
print('The index of e:', index) # 1
=== Insérer un élément n'importe où ===
l.insert(0, "new") # insert "new" at the beginning of the list
=== Tri ===
sorted_list = sorted(list_to_sort)
sorted_list = sorted(list_to_sort, key=lambda e: e['dict_key'])
list_to_sort.sort()
Ces fonctions acceptent un paramètre ''reverse=True'' pour trier dans l'ordre décroissant.
=== Map ===
list_mapped = map(lambda x: x*2, initial_list)
=== S'assurer qu'il n'y a pas de doublons ===
[[https://stackoverflow.com/questions/1541797/how-do-i-check-if-there-are-duplicates-in-a-flat-list|Source]]
Si les éléments sont hashables:
len(your_list) != len(set(your_list))
Sinon, une méthode avec une complexité plus importante:
any(thelist.count(x) > 1 for x in thelist)
=== Somme terme à terme de deux listes ===
[[https://stackoverflow.com/questions/18713321/element-wise-addition-of-2-lists|Source]]
# Est plus rapide
from operator import add
list(map(add, list1, list2))
[sum(x) for x in zip(list1, list2)]
Si la vitesse importe vraiment, il est aussi possible de le faire avec Numpy encore plus rapidement.
==== Chaînes de caractères ====
=== Formatage de chaînes de caractères ===
[[https://pyformat.info/]], [[https://fstring.help/cheat/]]
Il faut doubler les accolades pour qu'elles soient ignorées par Python:
"\\texttt{{{}}}".format('COPY') # = "\texttt{COPY}"
=== Générer une chaîne de caractères aléatoires ===
import string
import random
def generate_random_string(size = 40, chars = string.ascii_lowercase + string.digits):
return ''.join(random.choice(chars) for _ in range(size))
=== Enlever les espaces de début et fin de chaîne ===
[[https://stackoverflow.com/questions/1185524/how-do-i-trim-whitespace|Source]]
s = " abc "
print(s.strip())
=== Formater un flottant en texte ===
[[https://stackoverflow.com/questions/6149006/display-a-float-with-two-decimal-places-in-python|Source]]
format(2.03, '.5f') # '2.03000'
=== Trouver une sous-chaîne ===
s = "the dude is a cool dude"
s.find('dude') # 4
=== Tester si une chaîne contient une lettre ===
any(c.isalpha() for c in s)
=== Sur plusieurs lignes ===
[[https://www.techbeamers.com/python-multiline-string/]]
# Préserve les retours à la ligne dans la chaîne de caractère:
s = """
multi
ligne
"""
# Pour juste éviter d'avoir un code trop large:
s = ("texte"
"sur la"
"même ligne")
=== Tester si c'est un nombre ===
[[https://stackoverflow.com/questions/1265665/how-can-i-check-if-a-string-represents-an-int-without-using-try-except]]
'12'.isdigit()
=== Trouver le préfixe commun ===
* [[https://stackoverflow.com/questions/6718196/determine-prefix-from-a-set-of-similar-strings]]
* https://docs.python.org/3/library/os.path.html#os.path.commonprefix
import os
os.path.commonprefix([str1, str2])
=== Connaître la langue d'un texte ===
* [[https://stackoverflow.com/questions/39142778/how-to-determine-the-language-of-a-piece-of-text/47106810]]
L'installation de Polyglot est un peu particulière ([[https://stackoverflow.com/questions/64886067/polyglot-importerror-cannot-import-name-locale-from-icu|source]]) :
pip install numpy six icu
pip install pyicu
pip install pycld2
pip install morfessor
from polyglot.text import Text
if Text(txt).language.code not in ["en", "fr"]:
printf("...")
==== Temps ====
=== Enlever les secondes d'une date ===
dtwithoutseconds = dt.replace(second=0, microsecond=0)
=== Récupérer le temps actuel ===
import datetime
t = datetime.datetime.now() # datetime.datetime(2009, 1, 6, 15, 8, 24, 78915)
t = datetime.datetime.now().time() # datetime.time(15, 8, 24, 78915)
t = datetime.datetime.now().timestamp() # 1575914832.536088
=== Différence de temps ===
t1 = datetime.datetime.now()
t2 = datetime.datetime.now()
delta = t2-t1 # datetime.timedelta(seconds=231, microseconds=573812), peut contenir des jours
(t2-t1).seconds # 231
(t2-t1).total_seconds() # 231.573812, converti tout en secondes
delta.days
=== Arithmétique sur les temps ===
import datetime
some_date -= datetime.timedelta(days=90)
=== Str vers date ===
>>> from datetime import date
>>> date.fromisoformat('2019-12-04')
datetime.date(2019, 12, 4)
À partir de la version 3.7.
* [[https://www.journaldev.com/23365/python-string-to-datetime-strptime]]
>>> import datetime
>>> d = datetime.datetime.strptime(date_str, '%m-%d-%Y').date()
=== Date vers Str ===
print(date_var.strftime("format"))
[[https://docs.python.org/3/library/datetime.html#strftime-and-strptime-format-codes|Références des formats possibles]]
=== Mesurer des durées ===
[[https://stackoverflow.com/questions/7370801/how-do-i-measure-elapsed-time-in-python|Source]]
from timeit import default_timer as timer
start = timer()
# ...
end = timer()
print(end - start) # Time in seconds, e.g. 5.38091952400282
==== Regex ====
* https://regex101.com/
=== Vérifier le respect d'un pattern ===
import re
pattern = re.compile("regex\d+")
m = pattern.match("string to test")
if m is not None:
# "string to test" matches the regex
=== Capturer des motifs ===
p = re.compile(r"^.+\s+(\d{2})/(\d{2})$")
m = p.match("abc 25/11")
if m is not None:
day = int(m.group(1))
month = int(m.group(2))
Trouver toutes les occurrences qui correspondent à un motif ([[https://stackoverflow.com/questions/4697882/how-can-i-find-all-matches-to-a-regular-expression-in-python|source]]) :
re.findall( r'all (.*?) are', 'all cats are smarter than dogs, all dogs are dumber than cats')
# Output: ['cats', 'dogs']
=== Remplacer un motif ===
re.sub(r'[\x00-\x08\x0B-\x0C\x0E-\x1F]', '', content)
==== Flottants ====
=== Tronquer un flottant ===
Utiliser la fonction ''round'':
round(1.23456, 3) # 1.235
=== Tester si une chaîne est un flottant ===
s.replace('.','',1).isdigit()
=== Tester si un flottant est NaN ===
import math
math.isnan(f)
==== Divers ====
=== Condition ternaire ===
condition_if_true if condition else condition_if_false
=== Tester le type d'une variable ===
if isinstance(x, dict):
print("x is dict")
=== Exécuter une commande système ===
import os
code_retour = os.system('ls')
Attention, chaque commande se place dans le dossier d’exécution du script, il n'y pas de persistance des déplacements dans l'arborescence au sein des différents appels à ''system()''.
Pour capturer ce qui est écrit sur la sortie standard ([[https://stackoverflow.com/a/18739828|source]]):
import subprocess
out = subprocess.check_output("ls", text=True)
print(out)
out_with_stderr = subprocess.check_output("ls", text=True, stderr=subprocess.STDOUT)
=== Quitter le programme avec un code d'erreur spécifique ===
import sys
sys.exit(1)
=== Générer un nombre aléatoire ===
Entre 0 et 1:
import random
x = random.random()
Entre deux entiers:
import random
x = random.randint(10, 25) # 10 <= x <= 25
=== Manipuler l’hexadécimal ===
[[https://stackoverflow.com/questions/209513/convert-hex-string-to-int-in-python|Source]]
Conversion de hexadécimal en décimal:
x = int("deadbeef", 16)
y = int("0xdeadbeef", 0)
''0'' indique à Python de trouver par lui-même la base.
Conversion de décimal en hexadécimal:
x = hex(10)
On peut manipuler l'hexadécimal directement dans la console en préfixant les nombres par ''0x''.
=== Convertir un nombre en binaire ===
bin(14) # '0b1110'
=== Sleep ===
import time
time.sleep(5) # secondes
=== Savoir si la sortie est redirigée ===
[[https://stackoverflow.com/a/1512526|Source]]
On cherche à savoir si ''stdout'' est différent de ''stdin'':
import os
redirected_to_file = not (os.fstat(0) == os.fstat(1))
Une solution plus simple (et semble plus fonctionnelle), mais pas forcément valide avec Windows :
import sys
if sys.stdout.isatty():
print "Not redirected"
else:
sys.stderr.write("Redirected!\n")
=== Obtenir le nom des arguments d'une fonction ===
[[https://stackoverflow.com/questions/218616/how-to-get-method-parameter-names|Source]]
import inspect
param_names = inspect.getfullargspec(f)[0]
=== Lire l'entrée standard ===
[[https://stackoverflow.com/questions/1450393/how-do-you-read-from-stdin|Source]]
import sys
lines = []
for line in sys.stdin:
lines.append(line)
On sort de la boucle lorsque l'entrée standard est fermée.
=== Connaître le nom du script exécuté ===
[[https://stackoverflow.com/questions/4152963/get-name-of-current-script-in-python|Source]]
import os
os.path.basename(__file__)
==== Dictionnaires ====
[[https://realpython.com/iterate-through-dictionary-python/]]
a_dict = {'color': 'blue', 'fruit': 'apple', 'pet': 'dog'}
for key in a_dict:
print(key, '->', a_dict[key])
for key, value in a_dict.items():
print(key, '->', value)
for value in a_dict.values():
print(value)
=== Tri ===
Par valeur:
{k: v for k, v in sorted(x.items(), key=lambda item: item[1])}
==== Parser du XML ====
* [[https://docs.python.org/3/library/xml.dom.minidom.html]]
* [[https://www.fil.univ-lille1.fr/~marvie/python/chapitre4.html]]
* [[https://stackoverflow.com/a/1912516]]
doc = minidom.parse("file.xml")
systems = doc.getElementsByTagName("System")
for s in systems:
n = s.getElementsByTagName("Node")
name = n[0].getElementsByTagName("NodeDesc")[0].firstChild.data
uid = n[0].attributes["id"].value
==== Énumérations ====
[[https://docs.python.org/fr/3/library/enum.html]]
from enum import Enum
class Direction(Enum):
TOP = 0
BOTTOM = 1
LEFT = 2
RIGHT = 3
d = Direction.TOP
On peut accéder à la valeur de l'élément de l'énumération:
Direction.TOP.value # 0
Pour faciliter la représentation des éléments:
class CompMetric(Enum):
BANDWIDTH = "bandwidth"
TIME = "time"
def __repr__(self):
return self.name
==== JSON ====
Afficher correctement en objet dans le format JSON:
import json
print(json.dumps(data, ensure_ascii=False, indent=4)) # ensure_ascii=False permet d'afficher correctement l'utf-8
==== Débugguer un segfault ====
* [[https://stackoverflow.com/questions/16731115/how-to-debug-a-python-segmentation-fault]]
* https://docs.python.org/3/library/faulthandler.html
export PYTHONFAULTHANDLER=1