Comment écrire un module / package Python?

375

J'ai fait des scripts Python pour des tâches simples au travail et je n'ai jamais vraiment pris la peine de les empaqueter pour que les autres les utilisent. Maintenant, j'ai été chargé de créer un wrapper Python pour une API REST. Je n'ai absolument aucune idée de comment commencer et j'ai besoin d'aide.

Ce que j'ai:

(Je veux juste être aussi précis que possible) J'ai le virtualenv prêt, il est également dans github , le fichier .gitignore pour python est là aussi, plus, la bibliothèque de requêtes pour interagir avec l'API REST. C'est ça.

Voici l'arborescence de répertoires actuelle

.
├── bin
   └── /the usual stuff/
├── include
   └── /the usual stuff/
├── lib
   └── python2.7
       └── /the usual stuff/
├── local
   └── /the usual stuff/
└── README.md

27 directories, 280 files

Je ne sais même pas où placer les fichiers .py, si j'en crée un.

Ce que je voulais faire:

Rendre un module python installable avec "pip install ..."

Si possible, je veux un processus général étape par étape sur l'écriture de modules Python.

yowmamasita
la source
15
Je commencerais par le chapitre 6 du tutoriel (2.7) , ou ici pour 3.x Recherchez le tutoriel du module python sur Internet et vous en trouverez beaucoup d'autres.
Roland Smith
6
Personne n'a répondu à la partie pip
whackamadoodle3000
github.com/MacHu-GWU/pygitrepo-project cette bibliothèque vous aide à créer un squelette de projet à partir de zéro, et la fonctionnalité dont vous avez besoin est prête à l'emploi .
MacSanhe

Réponses:

424

Un module est un fichier contenant des définitions et des instructions Python. Le nom de fichier est le nom du module avec le suffixe.py

créer hello.pypuis écrire la fonction suivante comme son contenu:

def helloworld():
   print "hello"

Ensuite, vous pouvez importer hello:

>>> import hello
>>> hello.helloworld()
'hello'
>>>

Pour regrouper de nombreux .pyfichiers, placez-les dans un dossier. Tout dossier avec un __init__.pyest considéré comme un module par python et vous pouvez les appeler un package

|-HelloModule
  |_ __init__.py
  |_ hellomodule.py

Vous pouvez continuer avec l'instruction d'importation sur votre module de la manière habituelle.

Pour plus d'informations, voir 6.4. Forfaits .

Anuj
la source
7
ce dernier serait-il: de HellowModule import hellomodule? Est-ce que ça pourrait être bonjour dans le dossier du module, donc ce serait de HelloModule importation bonjour
nycynik
Je joue actuellement avec Python et cette réponse doit être l'une des plus utiles que j'ai rencontrées. Explique très bien, merci.
Darren Wainwright
la commande "pip install" ne fonctionnera pas, vous devez également être dans le même répertoire pour l'utiliser
Math Coder 101
234

Python 3 - MISE À JOUR 18 novembre 2015

J'ai trouvé la réponse acceptée utile, mais j'ai souhaité développer plusieurs points au profit des autres en fonction de mes propres expériences.

Module: Un module est un fichier contenant des définitions et des instructions Python. Le nom de fichier est le nom du module avec le suffixe .py ajouté.

Exemple de module : Supposons que nous ayons un seul script python dans le répertoire courant, ici je l'appelle mymodule.py

Le fichier mymodule.py contient le code suivant:

def myfunc():
    print("Hello!")

Si nous exécutons l'interpréteur python3 à partir du répertoire actuel, nous pouvons importer et exécuter la fonction myfunc des différentes manières suivantes (vous choisirez généralement l'une des options suivantes):

>>> import mymodule
>>> mymodule.myfunc()
Hello!
>>> from mymodule import myfunc
>>> myfunc()
Hello!
>>> from mymodule import *
>>> myfunc()
Hello!

Ok, donc c'était assez facile.

Supposons maintenant que vous avez besoin de placer ce module dans son propre dossier dédié pour fournir un espace de noms de module, au lieu de simplement l'exécuter ad-hoc à partir du répertoire de travail actuel. C'est là qu'il vaut la peine d'expliquer le concept d'un package .

Package : Les packages sont un moyen de structurer l'espace de noms des modules de Python en utilisant des «noms de modules en pointillés». Par exemple, le nom de module AB désigne un sous-module nommé B dans un package nommé A. Tout comme l'utilisation de modules évite aux auteurs de différents modules d'avoir à se soucier des noms de variables globaux les uns des autres, l'utilisation de noms de modules en pointillés sauve les auteurs des packages multi-modules comme NumPy ou la bibliothèque d'imagerie Python d'avoir à se soucier des noms des modules des autres.

Exemple de package : supposons maintenant que nous avons le dossier et les fichiers suivants. Ici, mymodule.py est identique à avant et __init__.py est un fichier vide:

.
└── mypackage
    ├── __init__.py
    └── mymodule.py

Les fichiers __init__.py sont requis pour que Python traite les répertoires comme contenant des packages. Pour plus d'informations, veuillez consulter le lien vers la documentation des modules fourni plus loin.

Notre répertoire de travail actuel est un niveau au-dessus du dossier ordinaire appelé mypackage

$ ls
mypackage

Si nous exécutons maintenant l'interpréteur python3, nous pouvons importer et exécuter le module mymodule.py contenant la fonction requise myfunc des différentes manières suivantes (vous devriez généralement choisir l'une des options suivantes):

>>> import mypackage
>>> from mypackage import mymodule
>>> mymodule.myfunc()
Hello!
>>> import mypackage.mymodule
>>> mypackage.mymodule.myfunc()
Hello!
>>> from mypackage import mymodule
>>> mymodule.myfunc()
Hello!
>>> from mypackage.mymodule import myfunc
>>> myfunc()
Hello!
>>> from mypackage.mymodule import *
>>> myfunc()
Hello!

En supposant que Python 3, il existe une excellente documentation sur: Modules

En termes de conventions de dénomination pour les packages et les modules, les directives générales sont données dans PEP-0008 - veuillez consulter Noms des packages et des modules

Les modules doivent avoir des noms courts tout en minuscules. Les traits de soulignement peuvent être utilisés dans le nom du module s'il améliore la lisibilité. Les packages Python doivent également avoir des noms courts tout en minuscules, bien que l'utilisation de soulignements soit déconseillée.

arcseldon
la source
5
Belle explication simple. Que faire si vous souhaitez conserver un autre dossier dans mypackage?
Anuj Gupta
3
L'inclusion dépend totalement de ce que vous avez écrit. Dans le cas où vous placez des éléments en dehors d'une fonction sur votre module, vous les déclenchez lorsque vous appelez like import mypackage. Dans le cas où vous voulez importer juste une fonction d'un module (même un fichier) est préférable d'utiliser from module import function. Dans le cas d'un sous-dossier from subfolder.module import function, vous pouvez simplement appeler function()sans déclencher d'autres parties de code. Aussi, ne l'utilisez pas from module import *si vous n'en avez pas vraiment besoin.
m3nda
5
La seule question qui reste est de savoir comment puis-je obtenir le package pour tout importer import mypackage? L'ajout import mymoduleà __init__.pyne fonctionne pas ..
576i
Belle explication! cependant, j'ai une question si numpy est un package comment puis-je exécuter numpy.cos (1) dans mon interpréteur car cela semble être un nom de module entre les deux disparaît. Non?
user1935724
3
Et pip?
whackamadoodle3000
199

Étant donné que personne n'a encore abordé cette question du PO:

Ce que je voulais faire:

Rendre un module python installable avec "pip install ..."

Voici un exemple minimal absolu, montrant les étapes de base de la préparation et du téléchargement de votre package vers PyPI à l'aide de setuptoolset twine.

Ce n'est en aucun cas un substitut à la lecture au moins du tutoriel , il y a beaucoup plus que ce qui est couvert dans cet exemple très basique.

La création du package lui-même est déjà couverte par d'autres réponses ici, alors supposons que nous avons cette étape couverte et notre structure de projet comme ceci:

.
└── hellostackoverflow/
    ├── __init__.py
    └── hellostackoverflow.py

Pour l'utiliser setuptoolspour le packaging, nous devons ajouter un fichier setup.py, celui-ci va dans le dossier racine de notre projet:

.
├── setup.py
└── hellostackoverflow/
    ├── __init__.py
    └── hellostackoverflow.py

Au minimum, nous spécifions les métadonnées de notre package, notre setup.pyressemblerait à ceci:

from setuptools import setup

setup(
    name='hellostackoverflow',
    version='0.0.1',
    description='a pip-installable package example',
    license='MIT',
    packages=['hellostackoverflow'],
    author='Benjamin Gerfelder',
    author_email='[email protected]',
    keywords=['example'],
    url='https://github.com/bgse/hellostackoverflow'
)

Depuis que nous avons défini license='MIT', nous incluons une copie dans notre projet comme LICENCE.txt, à côté d'un fichier readme dans reStructuredText comme README.rst:

.
├── LICENCE.txt
├── README.rst
├── setup.py
└── hellostackoverflow/
    ├── __init__.py
    └── hellostackoverflow.py

À ce stade, nous sommes prêts à commencer à emballer en utilisant setuptools, si nous ne l'avons pas déjà installé, nous pouvons l'installer avec pip:

pip install setuptools

Pour ce faire et créer un source distribution, dans notre dossier racine de projet, nous appelons notre setup.pydepuis la ligne de commande, en spécifiant que nous voulons sdist:

python setup.py sdist

Cela créera notre package de distribution et les informations sur les œufs, et aboutira à une structure de dossiers comme celle-ci, avec notre package dans dist:

.
├── dist/
├── hellostackoverflow.egg-info/
├── LICENCE.txt
├── README.rst
├── setup.py
└── hellostackoverflow/
    ├── __init__.py
    └── hellostackoverflow.py

À ce stade, nous avons un package que nous pouvons installer à l'aide pipde notre racine de projet (en supposant que vous avez tous les noms comme dans cet exemple):

pip install ./dist/hellostackoverflow-0.0.1.tar.gz

Si tout se passe bien, nous pouvons maintenant ouvrir un interpréteur Python, je dirais quelque part en dehors de notre répertoire de projet pour éviter toute confusion, et essayer d'utiliser notre nouveau package brillant:

Python 3.5.2 (default, Sep 14 2017, 22:51:06) 
[GCC 5.4.0 20160609] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> from hellostackoverflow import hellostackoverflow
>>> hellostackoverflow.greeting()
'Hello Stack Overflow!'

Maintenant que nous avons confirmé l'installation et le fonctionnement du package, nous pouvons le télécharger sur PyPI.

Comme nous ne voulons pas polluer le référentiel en direct avec nos expériences, nous créons un compte pour le référentiel de test et installons twinepour le processus de téléchargement:

pip install twine

Maintenant que nous y sommes presque, avec notre compte créé, nous disons simplement twinede télécharger notre package, il demandera nos informations d'identification et téléchargera notre package dans le référentiel spécifié:

twine upload --repository-url https://test.pypi.org/legacy/ dist/*

Nous pouvons maintenant nous connecter à notre compte sur le référentiel de test PyPI et nous émerveiller de notre package fraîchement téléchargé pendant un certain temps, puis le saisir en utilisant pip:

pip install --index-url https://test.pypi.org/simple/ hellostackoverflow

Comme nous pouvons le voir, le processus de base n'est pas très compliqué. Comme je l'ai dit plus tôt, il y a beaucoup plus que couvert ici, alors allez-y et lisez le tutoriel pour une explication plus approfondie.

bgse
la source
Mon package sera-t-il publié juste après setuptools?
U10-Forward
@ U9-Forward Non, la publication est terminée avec twine, mais vous pouvez tester votre package localement avant de le publier après l'avoir créé avec setuptools.
bgse
9

Une fois que vous avez défini les commandes que vous avez choisies, vous pouvez simplement faire glisser et déposer le fichier enregistré dans le dossier Lib de vos fichiers de programme python.

>>> import mymodule 
>>> mymodule.myfunc()
Dreamatronix
la source
2

Créez un fichier nommé "hello.py"

Si vous utilisez Python 2.x

def func():
    print "Hello"

Si vous utilisez Python 3.x

def func():
    print("Hello")

Exécutez le fichier. Ensuite, vous pouvez essayer ce qui suit:

>>> import hello
>>> hello.func()
Hello

Si vous voulez un peu de mal, vous pouvez utiliser ce qui suit:

Si vous utilisez Python 2.x

def say(text):
    print text

Si vous utilisez Python 3.x

def say(text):
    print(text)

Voir celui sur la parenthèse à côté du définir? C'est important. C'est celui que vous pouvez utiliser dans la définition.

Texte - Vous pouvez l'utiliser lorsque vous voulez que le programme dise ce que vous voulez. Selon son nom, c'est du texte. J'espère que vous savez ce que signifie le texte. Cela signifie "mots" ou "phrases".

Exécutez le fichier. Ensuite, vous pouvez essayer ce qui suit si vous utilisez Python 3.x:

>>> import hello
>>> hello.say("hi")
hi
>>> from hello import say
>>> say("test")
test

Pour Python 2.x - Je suppose que c'est la même chose avec Python 3? Aucune idée. Corrigez-moi si j'ai fait une erreur sur Python 2.x (je connais Python 2 mais je suis habitué à Python 3)

Kakkoiikun
la source
2

J'ai créé un projet pour lancer facilement un squelette de projet à partir de zéro . https://github.com/MacHu-GWU/pygitrepo-project .

Et vous pouvez créer un projet de test, par exemple le let, learn_creating_py_package.

Vous pouvez apprendre quel composant vous devez avoir à différentes fins comme :

  • créer virtualenv
  • s'installer
  • courir moins fort
  • exécuter la couverture du code
  • créer un document
  • déployer le document
  • exécuter unittest dans différentes versions de python
  • déployer sur PYPI

L'avantage d'utiliser pygitrepoest que ces fastidieux sont automatiquement créés lui - même et adapter votre package_name, project_name, github_account, document host service, windows or macos or linux.

C'est un bon endroit pour apprendre à développer un projet python comme un pro.

J'espère que cela pourrait vous aider.

Je vous remercie.

MacSanhe
la source