13 tips pour Python
Une série de 6 articles présentant les outils à mettre en place pour le dev Python en 2020. Au programme:
- pyenv et Poetry pour la version python et les dépendances
- click pour la cli
- requests pour les calls HTTP
- pytest, coverage et nox pour les tests units
- black, flake8 et pre-commit pour le code linting
- mypy pour le static typing (pas utilisé encore)
- sphinx et readthedocs pour la doc
- github actions pour le ci/cd
Beaucoup de bonnes pratiques et de plugins flake8 pour automatiser un max de checks...
La série d'article est aussi accompagnée d'un repo qui met tout en pratique: https://github.com/cjolowicz/hypermodern-python
Quelques tips pour debugger du code python avec print()
, notamment:
- Debug variables with f-strings and
=
:print(f"{myvar=}")
- Use
locals()
to debug all local variables:print(locals())
- Use
vars()
to debug all of an object’s attributes:print(vars(myobject))
Un tuto très complet pour apprendre à interagir avec des APIs externes en Python.
Une description détaillée des nouveautés de Python 3.9
Pour utiliser gcloud
(cli GCP) avec Python3 (>=3.4) au lieu de Python2:
# Use the python3 interpreter on your path
$ export CLOUDSDK_PYTHON=python3
Un simple outils Python en ligne de commande qui reste la taille d'une image Docker et retourne une erreur si celle ci dépasse une taille donnée. A intégrer dans les CI pour s'assurer que les images Docker ne grossissent pas exponentiellement au fil du temps.
Avec Python2, dict.keys()
, dict.values()
et dict.items()
retournent une liste. Avec Python3, ces méthodes retournent un objet de type "dictionary view".
Utiliser une loop avec une de ces 3 méthodes renvoie l'erreur suivante: 'dict object' has no attribute \"dict_keys(['hosts'])
Il faut utiliser le filtre list pour convertir l'objet en liste:
vars:
hosts:
testhost1: 127.0.0.2
testhost2: 127.0.0.3
tasks:
- debug:
msg: '{{ item }}'
# Only works with Python 2
#loop: "{{ hosts.keys() }}"
# Works with both Python 2 and Python 3
loop: "{{ hosts.keys() | list }}"
Sur les distribs disposant de python < 2.7.9 (ubuntu 14.04 par exemple), les modules ansible apt_key et apt_repository ne gèrent pas les urls en HTTPS.
example:
fatal: [localhost]: FAILED! => {"changed": false, "msg": "Failed to validate the SSL certificate for packages.elastic.co:443. Make sure your managed systems have a valid CA certificate installed. If the website serving the url uses SNI you need python >= 2.7.9 on your managed machine (the python executable used (/usr/bin/python) is version: 2.7.6 (default, Nov 13 2018, 12:45:42) [GCC 4.8.4]) or you can install the `urllib3`, `pyOpenSSL`, `ndg-httpsclient`, and `pyasn1` python modules to perform SNI verification in python >= 2.6. You can use validate_certs=False if you do not need to confirm the servers identity but this is unsafe and not recommended. Paths checked for this platform: /etc/ssl/certs, /etc/pki/ca-trust/extracted/pem, /etc/pki/tls/certs, /usr/share/ca-certificates/cacert.org, /etc/ansible. The exception msg was: hostname 'packages.elastic.co' doesn't match 'e.sni.fastly.net'."}
Il est nécessaire d'installer les packages python-urllib3
, python-openssl
, python-pyasn1
, python-pip
et pip ndg-httpsclient
pour que cela soit fonctionnel.
example:
- name: Debian - ensure python-urllib3, python-openssl, python-pyasn1 & python-pip are installed
apt:
name: python-urllib3,python-openssl,python-pyasn1,python-pip
state: present
when: ansible_distribution_release == "trusty"
- name: Debian - ensure ndg-httpsclient pip is installed
pip:
name: ndg-httpsclient
state: present
when: ansible_distribution_release == "trusty"
Example d'utilisation de pre-commit git pour forcer le formattage de code python avec black et flake8
12 bonnes pratiques a mettre en place quand on publie du code python en open source
Erreur rencontrée avec Ansible 2.6.5, Python 2.7.15 et MacOS 10.13 lors de l'execution d'un playbook sur un Windows 2016 Server:
$ ansible-playbook playbook.yml
PLAY [Prepare instance] *********************************************************************************************************************************************************************************************************************************************
TASK [Gathering Facts] **********************************************************************************************************************************************************************************************************************************************
Friday 05 October 2018 11:32:23 +0200 (0:00:00.072) 0:00:00.072 ********
objc[11299]: +[__NSPlaceholderDate initialize] may have been in progress in another thread when fork() was called.
objc[11299]: +[__NSPlaceholderDate initialize] may have been in progress in another thread when fork() was called. We cannot safely call it or ignore it in the fork() child process. Crashing instead. Set a breakpoint on objc_initializeAfterForkError to debug.
^C [ERROR]: User interrupted execution
A priori c'est lié à la gestion des forks dans MacOS High Sierra. Le workaround est de faire un export OBJC_DISABLE_INITIALIZE_FORK_SAFETY=YES
avant de lancer Ansible
Méthode pour faire du blue-green deployment sur AWS avec des scripts python utilisant boto3 et fabric.
Un reformatteur de code python développé par Google.
$ pip install yapf
$ yapf my_file.py
Un webhook listener en Python avec Flask pour exécuter des actions automatiquement après un push git sur GitHub ou BitBucket:
import os
from sys import platform as _platform
from flask import Flask
from flask import request
app = Flask(__name__)
@app.route('/webhook', methods=['POST'])
def tracking():
data = request.get_json()
commit_author = data['actor']['username']
commit_hash = data['push']['changes'][0]['old']['target']['hash'][:7]
commit_url = data['push']['changes'][0]['old']['target']['links']['html']['href']
print 'Webhook received! %s committed %s: %s' % (commit_author, commit_hash, commit_url)
return 'OK'
if __name__ == '__main__':
app.run(host='0.0.0.0', port=5000, debug=True)
Quelques commandes pratiques pour iPython
Celery est une librairie Python qui permet de gérer des files d'attentes pour des traitements batchs asynchrones ou schedulés.
Il est possible de plugger Celery a un backend parmi Redis, AWS SQS, RabbitMQ, MongoDB ou une base de données par exemple.
Un script Python pour générer les serveurs et rôles utilisé par Fabric de façon dynamique en utilisant l'API AWS.
Ce script génère les rôles en se basant sur le nom de l'instance.
Je préfère une approche utilisant les tags AWS pour gérer les rôles.
C'est plus compliqué à gérer, mais ça laisse beaucoup plus de flexibilité.
Explication de la POO en 8 parties:
- http://sametmax.com/le-guide-ultime-et-definitif-sur-la-programmation-orientee-objet-en-python-a-lusage-des-debutants-qui-sont-rassures-par-les-textes-detailles-qui-prennent-le-temps-de-tout-expliquer-partie-2/
- http://sametmax.com/le-guide-ultime-et-definitif-sur-la-programmation-orientee-objet-en-python-a-lusage-des-debutants-qui-sont-rassures-par-les-textes-detailles-qui-prennent-le-temps-de-tout-expliquer-partie-3/
- http://sametmax.com/le-guide-ultime-et-definitif-sur-la-programmation-orientee-objet-en-python-a-lusage-des-debutants-qui-sont-rassures-par-les-textes-detailles-qui-prennent-le-temps-de-tout-expliquer-partie-4/
- http://sametmax.com/le-guide-ultime-et-definitif-sur-la-programmation-orientee-objet-en-python-a-lusage-des-debutants-qui-sont-rassures-par-les-textes-detailles-qui-prennent-le-temps-de-tout-expliquer-partie-5/
- http://sametmax.com/le-guide-ultime-et-definitif-sur-la-programmation-orientee-objet-en-python-a-lusage-des-debutants-qui-sont-rassures-par-les-textes-detailles-qui-prennent-le-temps-de-tout-expliquer-partie-6/ (*)
- http://sametmax.com/le-guide-ultime-et-definitif-sur-la-programmation-orientee-objet-en-python-a-lusage-des-debutants-qui-sont-rassures-par-les-textes-detailles-qui-prennent-le-temps-de-tout-expliquer-partie-7/
- http://sametmax.com/le-guide-ultime-et-definitif-sur-la-programmation-orientee-objet-en-python-a-lusage-des-debutants-qui-sont-rassures-par-les-textes-detailles-qui-prennent-le-temps-de-tout-expliquer-partie-8/