pip install my-package
Un module est un fichier python .py
. Généralement les modules contiennent du code organisé sous forme de fonctions et/ou classes remplissant une même fonction: par exemple le module python math.py
Un package est une collection de dossiers et sous-dossiers contenant des modules
Chacun de ces dossiers doit contenir un fichier __init__.py
Les conventions de python PEP recommandent la syntaxe suivante:
Configuration minimale pour créer un package my-package
avec un seul module lib
:
(plus de détails sur la doc officielle de python)
my-project # dossier du projet (a mettre à la racine de votre dépot) setup.py # script d'installation des dépendances my-package/ # package __init__.py # définit my-package comme package python lib.py # module
Exemple d'un package sound
contenant deux sous-paquet formats
et effects
ainsi que plusieurs modules
sound/ # racine du package
__init__.py
setup.py
formats/ # sous package pour les conversions de formats
__init__.py
wavread.py # module
wavwrite.py
...
effects/ # sous package pour les effets de sons
__init__.py
echo.py
surround.py
reverse.py
...
Il contient des informations pour l'installation automatique des paquets et utilise le module setup
du package setuptools
, par exemple, pour installer notre package sound
on pourrait utiliser le code:
from setuptools import setup
from setuptools import find_packages
setup(name='sound',
description='A package for sound processing',
packages=['sound'],
version='0.1',
url='http://github.com/jonhdoe/sound',
author='John Doe',
author_email='johndoe@example.com',
license='GPL3',
)
Si votre projet contient un bon nombre de sous paquets, il peut être intéressant d'utiliser le module find_package
permettant de rechercher automatiquement les sous paquets:
setup(pakages=find_packages())
requirements.txt
¶le fichier requirements.txt
sert à renseigner toutes les dépendances nécessaires au bon fonctionnement du code dans votre paquet. Généralement, il est parsé par le fichier setup.py
pour s'assurer que l'installation de votre paquet inclue automatiquement les dépendances nécessaires:
sound/ # racine du package __init__.py setup.py requirements.txt # indique les dépendances pour votre paquet formats/ # sous package pour les conversions de formats __init__.py wavread.py # module wavwrite.py ... effects/ # sous package pour les effets de sons __init__.py echo.py surround.py reverse.py ...
# parse dependencies from requirements.txt
with open('requirements.txt') as f:
content = f.readlines()
requirements = [x.strip() for x in content]
setup(name='sound',
description='A package for sound processing',
version='0.1',
url='http://github.com/jonhdoe/sound',
author='John Doe',
author_email='johndoe@example.com',
license='GPL3',
packages=find_packages(),
install_requires=requirements
)
Pour plus de détails, lisez la documentation du package setuptools
Afin de pouvoir installer votre package depuis n'importe ou et le lancer automatiquement un script après installation, il est courant d'inclure un script shell
dans votre package, par exemple:
sound/ # racine du package __init__.py setup.py requirements.txt # indique les dépendances pour votre paquet scripts/ sound-run # script shell formats/ # sous package pour les conversions de formats __init__.py wavread.py # module wavwrite.py ... effects/ # sous package pour les effets de sons __init__.py echo.py surround.py reverse.py ...
Ce script sera automatiquement executé au moment de l'installation, en spécifiant le kwarg scripts
du fichier setup.py
:
# parse dependencies from requirements.txt
with open('requirements.txt') as f:
content = f.readlines()
requirements = [x.strip() for x in content]
setup(name='sound',
description='A package for sound processing',
version='0.1',
url='http://github.com/jonhdoe/sound',
author='John Doe',
author_email='johndoe@example.com',
license='GPL3',
packages=find_packages(),
install_requires=requirements,
scripts=['scripts/sound-run']
)
sound-run
Vous pouvez, par exemple, utilisez ce package, cookiecutter pour générer automatiquement vos packages !
pip install .
En cours de développement du package on souhaite généralement ne pas avoir à le réinstaller à chaque modification :
pip install -e .
avec pip: pip show my-package
avec conda: conda info pandas
import sound as sn
import sound.effects.echo
from sound.effects import echo
Je peux ensuite appeler la fonction echofilter
:
echo.echofilter(input, output, delay=0.7, atten=4)
Ou encore importer directement la echofilter
:
from sound.effects.echo import echofilter
echofilter(input, output, delay=0.7, atten=4)
En général, pour faciliter le déploiement de votre projet final, il est fortement conseillé de commencer à developper en ayant packagé son code des le départ!
Si ca n'est pas le cas, pour une utilisation locale uniquement par exemple, on peut importer le code d'un module en ajoutant le module au dans la variable d'environnement PYTHONPATH
Soit en rajoutant le nom de mon module dans la liste sys.path
, pour chaque module !!
import sys
sys.path.append('mon-module')
Soit, de manière permanente, en éditant la variable PYTHONPATH
dans le fichier de configuration de votre terminal
Par exemple dans un terminal bash, je peux éditer le fichier de configuration .bashrc
:
PYTHONPATH="/home/nico/DataScience/code/projets":$PYTHONPATH
export PYTHONPATH
Il est très important de documenter son package (si possible en anglais) pour faciliter la lecture du code, la compréhension de l'organisation de votre package, les instructions pour installer votre package, pour y contribuer, ...
Dans tous les langages, commenter son code est une habitude indispensable à prendre, il vous permettra de faciliter sa relecture par vous même ou un potentiel contributeur. Il est donc préférable de le faire en anglais pour que sa lecture soit accessible a un locuteur d'une autre langue
En python, la communauté a émis de nombreuses recommandations visant normaliser les bonnes pratiques des développeurs au travers des PEP(Python Enhancement Proposal). En particulier, les conventions du PEP 8 donnent des recommandations précises pour écrire et commenter son code, dont voici les principales règles:
# Aligned with opening delimiter.
foo = long_function_name(var_one, var_two,
var_three, var_four)
# Add 4 spaces (an extra level of indentation) to distinguish arguments from the rest.
def long_function_name(
var_one, var_two, var_three,
var_four):
print(var_one)
# Hanging indents should add a level.
foo = long_function_name(
var_one, var_two,
var_three, var_four)
my_list = [
1, 2, 3,
4, 5, 6,
]
# easy to match operators with operands
income = (gross_wages
+ taxable_interest
+ (dividends - qualified_dividends)
- ira_deduction
- student_loan_interest)
un import par ligne, sauf pour les imports concernant un même module:
import os
import sys
from subprocess import Popen, PIPE
les imports absolus sont à privilégier par rapport aux imports relatifs:
# absolute import
from datetime import datetime
from my_package.module import some_function
# relative import
# A dot indicates one directory up from the current location and two dots indicates two directories up and so on.
from .module_in_same_dir import some_function
from ..module_in_parent_dir import other_function
def greeting(name: str) -> str:
return 'Hello ' + name
De manière générale, c'est un string qui se place au début de chaque module
, fonction
, classe
ou méthode
en tant que définition décrivant les effets de cet objet. Néanmoins, les informations contenues dans le docstring varient en fonction de chacun des objets cités plus haut. Si vous respectez les conventions d'écriture, le docstring apparait dans l'attribut __doc__ special de cet objet et est affiché dans l'auto-complétion de la console python.
Voici un exemple de docstring respectant le PEP 257 pour une fonction:
def complex(real=0.0, imag=0.0):
"""Form a complex number.
Keyword arguments:
real -- the real part (default 0.0)
imag -- the imaginary part (default 0.0)
"""
if imag == 0.0 and real == 0.0:
return complex_zero
...
Il existe néanmoins différenttes variantes de format de doctring qui ne respectent pas complètement le PEP 257 mais plus agréables à lire, comme par exemple le format google ou celui de numpy. Pour plus de détails sur les docstring, voir cet article
Il est possible d'utiliser des outils pour formater automatiquement (linters) son code suivant les conventions PEP:
Le fichier README
est le mimimum de de documentation à écrire lorsque vous distribuez votre package ou votre logiciel afin de faciliter au maximum sa compréhension et son utilisation par d'autres développeurs
Le markdown est le format souvent utilisé pour écrire ce type de fichier sous forme README.md
. Par exemple, ce fichier est automatiquement lu et affiché en tant que description sur les plateformes comme Github, Gitlab, Bitbucket, ...
Je vous suggère d'y inclure au moins les paragraphes suivants:
# Project Title
## Project's description
What is this project usefull for ?
## Installation
How to install my software ?
## Sofware's usage
How to use my software ?
### Getting started
If you're software is quite complicating to use you can provide details exemple of specific usages
## Todo
Features that you want to implement in the future
## License
License that specify how to use, distribute and share your software
## Contributing/Code of conduct
Write your rules for contributors
Voici un bon exemple de README.md
d'un projet bien documenté