Come scrivere un modulo / pacchetto Python?


375

Ho realizzato script Python per semplici compiti sul lavoro e non mi sono mai preoccupato di impacchettarli per essere usati da altri. Ora mi è stato assegnato il compito di creare un wrapper Python per un'API REST. Non ho assolutamente idea di come iniziare e ho bisogno di aiuto.

Ciò che ho:

(Voglio solo essere il più specifico possibile) Ho il virtualenv pronto, è anche su github , c'è anche il file .gitignore per python, oltre alla libreria delle richieste per interagire con l'API REST. Questo è tutto.

Ecco l'albero delle directory corrente

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

27 directories, 280 files

Non so nemmeno dove mettere i file .py, se mai ne avessi fatto uno.

Cosa volevo fare:

Rendi installabile un modulo Python con "pip install ..."

Se possibile, desidero un processo passo-passo generale sulla scrittura dei moduli Python.


15
Vorrei iniziare con il capitolo 6 del tutorial (2.7) , o qui per 3.x Cerca in Internet il tutorial del modulo python e ne troverai molti altri.
Roland Smith,

6
Nessuno rispose alla parte di pip
whackamadoodle3000,

github.com/MacHu-GWU/pygitrepo-project questa libreria ti aiuta a creare da zero lo scheletro del progetto e la funzionalità di cui hai bisogno è pronta all'uso.
MacSanhe,

Risposte:


424

Un modulo è un file contenente definizioni e istruzioni di Python. Il nome del file è il nome del modulo con il suffisso.py

creare hello.pyquindi scrivere la seguente funzione come contenuto:

def helloworld():
   print "hello"

Quindi puoi importare hello:

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

Per raggruppare molti .pyfile, inseriscili in una cartella. Qualsiasi cartella con un __init__.pyè considerata un modulo da Python e puoi chiamarli un pacchetto

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

Puoi procedere con la dichiarazione di importazione sul tuo modulo nel solito modo.

Per ulteriori informazioni, vedere 6.4. Pacchetti .


7
sarebbe l'ultimo: da HellowModule importare hellomodule? Potrebbe essere ciao nella cartella del modulo, quindi sarebbe da HelloModule import hello
nycynik

Attualmente sto giocando con Python e questa risposta deve essere una delle più utili che abbia mai incontrato. Lo spiega molto bene, grazie.
Darren Wainwright,

il comando "pip install" non funzionerà, inoltre devi essere nella stessa directory per usarlo
Math Coder 101

234

Python 3 - AGGIORNATO il 18 novembre 2015

Ho trovato utile la risposta accettata, ma desideravo espandermi su diversi punti a beneficio degli altri in base alle mie esperienze.

Modulo: un modulo è un file contenente definizioni e istruzioni di Python. Il nome del file è il nome del modulo con il suffisso .py aggiunto.

Esempio di modulo : supponiamo di avere un singolo script Python nella directory corrente, qui lo chiamo mymodule.py

Il file mymodule.py contiene il seguente codice:

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

Se eseguiamo l'interprete python3 dalla directory corrente, possiamo importare ed eseguire la funzione myfunc nei seguenti modi diversi (in genere sceglieresti uno dei seguenti):

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

Ok, è stato abbastanza facile.

Ora supponiamo che abbiate la necessità di inserire questo modulo nella sua cartella dedicata per fornire uno spazio dei nomi del modulo, invece di eseguirlo ad hoc dalla directory di lavoro corrente. È qui che vale la pena spiegare il concetto di un pacchetto .

Pacchetto : i pacchetti sono un modo per strutturare lo spazio dei nomi dei moduli di Python usando "nomi dei moduli punteggiati". Ad esempio, il nome del modulo AB indica un sottomodulo denominato B in un pacchetto denominato A. Proprio come l'uso dei moduli salva gli autori di moduli diversi dal doversi preoccupare reciprocamente dei nomi delle variabili globali, l'uso dei nomi dei moduli punteggiati salva gli autori di pacchetti multi-modulo come NumPy o Python Imaging Library dal doversi preoccupare dei nomi dei moduli degli altri.

Esempio di pacchetto : supponiamo ora di avere i seguenti file e cartelle. Qui mymodule.py è identico a prima e __init__.py è un file vuoto:

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

I file __init__.py sono richiesti per fare in modo che Python tratti le directory come pacchetti contenenti. Per ulteriori informazioni, consultare il collegamento alla documentazione dei moduli fornito più avanti.

La nostra attuale directory di lavoro è un livello sopra la normale cartella chiamata mypackage

$ ls
mypackage

Se eseguiamo ora l'interprete python3, possiamo importare ed eseguire il modulo mymodule.py contenente la funzione richiesta myfunc nei seguenti modi diversi (in genere sceglieresti uno dei seguenti):

>>> 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!

Supponendo Python 3, c'è un'ottima documentazione su: Moduli

In termini di convenzioni di denominazione per pacchetti e moduli, le linee guida generali sono riportate in PEP-0008 - vedere Nomi di pacchetti e moduli

I moduli dovrebbero avere nomi brevi, tutti minuscoli. I caratteri di sottolineatura possono essere utilizzati nel nome del modulo se migliora la leggibilità. I pacchetti Python dovrebbero anche avere nomi brevi, tutti in minuscolo, sebbene l'uso di caratteri di sottolineatura sia sconsigliato.


5
Bella semplice spiegazione. Cosa succede se si desidera mantenere un'altra cartella all'interno del mypackage?
Anuj Gupta,

3
L'inclusione dipende totalmente da ciò che hai scritto. Nel caso in cui metti cose al di fuori di una funzione sul tuo modulo, la licenzierai quando chiami like import mypackage. Nel caso in cui desideri importare solo una funzione da un modulo (anche un file) è meglio usarla from module import function. Nel caso in una sottocartella in from subfolder.module import functionmodo da poter semplicemente chiamare function()senza fuoco altre parti di codice. Inoltre, non utilizzare from module import *se non è davvero necessario.
m3nda,

5
L'unica domanda rimasta è come posso ottenere il pacchetto su cui importare tutto import mypackage? L'aggiunta import mymodulea __init__.pynon funziona ..
576i

Spiegazione accurata! tuttavia, ho una domanda se numpy è un pacchetto come posso eseguire numpy.cos (1) nel mio interprete perché quello sembra essere un nome di modulo tra un messaggio e l'altro. No?
user1935724

3
Che ne dici di pip?
whackamadoodle3000,

199

Dal momento che nessuno ha ancora trattato questa domanda del PO:

Cosa volevo fare:

Rendi installabile un modulo Python con "pip install ..."

Ecco un esempio assolutamente minimo, che mostra i passaggi di base per preparare e caricare il pacchetto su PyPI utilizzando setuptoolse twine.

Questo non è affatto un sostituto per leggere almeno il tutorial , c'è molto di più di quello trattato in questo esempio di base.

La creazione del pacchetto stesso è già coperta da altre risposte qui, quindi supponiamo che abbiamo coperto quel passaggio e la nostra struttura del progetto in questo modo:

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

Per poterlo utilizzare setuptoolsper il packaging, dobbiamo aggiungere un file setup.py, questo va nella cartella principale del nostro progetto:

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

Come minimo, specifichiamo i metadati per il nostro pacchetto, il nostro setup.pysarebbe simile al seguente:

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='benjamin.gerfelder@gmail.com',
    keywords=['example'],
    url='https://github.com/bgse/hellostackoverflow'
)

Da quando abbiamo impostato license='MIT', includiamo una copia nel nostro progetto come LICENCE.txt, insieme a un file readme in reStructuredText come README.rst:

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

A questo punto, siamo pronti per iniziare a utilizzare il packaging setuptools, se non lo abbiamo già installato, possiamo installarlo con pip:

pip install setuptools

Per fare ciò e creare un source distribution, nella cartella principale del nostro progetto chiamiamo il nostro setup.pydalla riga di comando, specificando che vogliamo sdist:

python setup.py sdist

Ciò creerà il nostro pacchetto di distribuzione e le informazioni sull'uovo e comporterà una struttura di cartelle come questa, con il nostro pacchetto in dist:

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

A questo punto, abbiamo un pacchetto che possiamo installare usando pip, quindi dalla radice del nostro progetto (supponendo che tu abbia tutti i nomi come in questo esempio):

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

Se tutto va bene, ora possiamo aprire un interprete Python, direi da qualche parte al di fuori della nostra directory di progetto per evitare qualsiasi confusione, e provare a usare il nostro nuovo brillante pacchetto:

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!'

Ora che abbiamo confermato l'installazione e il funzionamento del pacchetto, possiamo caricarlo su PyPI.

Poiché non vogliamo inquinare il repository live con i nostri esperimenti, creiamo un account per il repository di test e installiamo twineper il processo di caricamento:

pip install twine

Ora siamo quasi arrivati, con il nostro account creato diciamo semplicemente twinedi caricare il nostro pacchetto, chiederà le nostre credenziali e caricherà il nostro pacchetto nel repository specificato:

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

Ora possiamo accedere al nostro account sul repository di test PyPI e meravigliarci del nostro pacchetto appena caricato per un po ', quindi afferrarlo usando pip:

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

Come possiamo vedere, il processo di base non è molto complicato. Come ho detto prima, c'è molto di più di quello trattato qui, quindi vai avanti e leggi il tutorial per una spiegazione più approfondita.


Il mio pacchetto verrà pubblicato subito dopo setuptools?
U10-Forward

@ U9-Forward No, la pubblicazione è twineterminata, ma è possibile testare il pacchetto localmente prima della pubblicazione dopo averlo creato con setuptools.
bgse

9

Dopo aver definito i comandi scelti, puoi semplicemente trascinare e rilasciare il file salvato nella cartella Lib nei file di programma di Python.

>>> import mymodule 
>>> mymodule.myfunc()

2

Crea un file chiamato "ciao.py"

Se si utilizza Python 2.x

def func():
    print "Hello"

Se stai usando Python 3.x

def func():
    print("Hello")

Esegui il file. Quindi, puoi provare quanto segue:

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

Se vuoi un po 'duro, puoi usare quanto segue:

Se si utilizza Python 2.x

def say(text):
    print text

Se stai usando Python 3.x

def say(text):
    print(text)

Vedi quello tra parentesi accanto a define? Questo è importante. È quello che è possibile utilizzare all'interno di define.

Testo: puoi usarlo quando vuoi che il programma dica quello che vuoi. Secondo il suo nome, è testo. Spero che tu sappia cosa significa il testo. Significa "parole" o "frasi".

Esegui il file. Quindi, puoi provare quanto segue se stai usando Python 3.x:

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

Per Python 2.x - Immagino la stessa cosa con Python 3? Nessuna idea. Correggimi se ho fatto un errore su Python 2.x (conosco Python 2 ma sono abituato a Python 3)


2

Ho creato un progetto per avviare facilmente uno scheletro di progetto da zero . https://github.com/MacHu-GWU/pygitrepo-project .

Ed è possibile creare un progetto di test, per esempio di let, learn_creating_py_package.

Puoi imparare quale componente dovresti avere per scopi diversi come :

  • crea virtualenv
  • si installa da solo
  • correre unittest
  • eseguire la copertura del codice
  • costruire documento
  • distribuire documento
  • eseguire unittest in diverse versioni di Python
  • distribuire su PYPI

Il vantaggio di utilizzare pygitrepoè che quei noiosi stesso si creano e si adattano automaticamente package_name, project_name, github_account, document host service, windows or macos or linux.

È un buon posto per imparare a sviluppare un progetto Python come un professionista.

Spero che questo possa aiutare.

Grazie.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.