Wie schreibe ich ein Python-Modul / Paket?

375

Ich habe Python-Skripte für einfache Aufgaben bei der Arbeit erstellt und mich nie wirklich darum gekümmert, sie für andere zu verpacken. Jetzt wurde ich beauftragt, einen Python-Wrapper für eine REST-API zu erstellen. Ich habe absolut keine Ahnung, wie ich anfangen soll und ich brauche Hilfe.

Was ich habe:

(Ich möchte nur so genau wie möglich sein.) Ich habe die virtuelle Umgebung bereit, sie ist auch in Github verfügbar . Die .gitignore-Datei für Python ist ebenfalls vorhanden. Außerdem gibt es die Anforderungsbibliothek für die Interaktion mit der REST-API. Das ist es.

Hier ist der aktuelle Verzeichnisbaum

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

27 directories, 280 files

Ich weiß nicht einmal, wo ich die .py-Dateien ablegen soll, falls ich jemals eine mache.

Was ich machen wollte:

Machen Sie ein Python-Modul mit "pip install ..." installierbar.

Wenn möglich, möchte ich einen allgemeinen Schritt-für-Schritt-Prozess zum Schreiben von Python-Modulen.

yowmamasita
quelle
15
Ich würde mit Kapitel 6 des Tutorials (2.7) beginnen oder hier für 3.x. Durchsuchen Sie das Internet nach dem Tutorial für Python-Module, und Sie werden viele andere finden.
Roland Smith
6
Niemand antwortete auf den Pip-Teil
whackamadoodle3000
github.com/MacHu-GWU/pygitrepo-project Mit dieser Bibliothek können Sie das Projektskelett von Grund auf neu erstellen. Die von Ihnen benötigte Funktion ist sofort einsatzbereit.
MacSanhe

Antworten:

424

Ein Modul ist eine Datei, die Python-Definitionen und -Anweisungen enthält. Der Dateiname ist der Modulname mit dem Suffix.py

Erstellen Sie hello.pydann die folgende Funktion als Inhalt:

def helloworld():
   print "hello"

Dann können Sie importieren hello:

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

Um viele .pyDateien zu gruppieren , legen Sie sie in einem Ordner ab. Jeder Ordner mit einem __init__.pywird von Python als Modul betrachtet, und Sie können sie als Paket bezeichnen

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

Sie können die import-Anweisung auf Ihrem Modul wie gewohnt ausführen.

Weitere Informationen finden Sie unter 6.4. Pakete .

Anuj
quelle
7
Wäre das letzte: von HellowModule Hellomodule importieren? Könnte das Hallo im Modulordner sein, so wäre es von HelloModule Import Hallo
Nycynik
Momentan spiele ich mit Python herum und diese Antwort muss eine der hilfreichsten sein, die mir begegnet sind. Erklärt es sehr gut, danke.
Darren Wainwright
Der Befehl "pip install" funktioniert nicht, außerdem müssen Sie sich im selben Verzeichnis befinden, um ihn verwenden zu können
Math Coder 101
234

Python 3 - AKTUALISIERT am 18. November 2015

Ich fand die akzeptierte Antwort nützlich, wollte aber aufgrund meiner eigenen Erfahrungen einige Punkte zum Nutzen anderer erweitern.

Modul: Ein Modul ist eine Datei, die Python-Definitionen und -Anweisungen enthält. Der Dateiname ist der Modulname mit dem angehängten Suffix .py.

Modulbeispiel : Angenommen, wir haben ein einzelnes Python-Skript im aktuellen Verzeichnis, hier nenne ich es mymodule.py

Die Datei mymodule.py enthält den folgenden Code:

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

Wenn wir den Python3-Interpreter aus dem aktuellen Verzeichnis ausführen, können wir die Funktion myfunc auf folgende Arten importieren und ausführen (normalerweise wählen Sie einfach eine der folgenden Möglichkeiten):

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

Ok, das war einfach genug.

Angenommen, Sie müssen dieses Modul in einem eigenen Ordner ablegen, um einen Modul-Namespace bereitzustellen, anstatt es nur ad-hoc aus dem aktuellen Arbeitsverzeichnis auszuführen. Hier lohnt es sich, das Konzept eines Pakets zu erläutern .

Paket : Pakete sind eine Möglichkeit, den Modul-Namespace von Python mithilfe von „gepunkteten Modulnamen“ zu strukturieren. Beispielsweise bezeichnet der Modulname AB ein Submodul mit dem Namen B in einem Paket mit dem Namen A. So wie die Verwendung von Modulen die Autoren verschiedener Module davon abhält, sich um die globalen Variablennamen der anderen zu kümmern, spart die Verwendung von gepunkteten Modulnamen die Autoren von Paketen mit mehreren Modulen wie NumPy oder der Python Imaging Library, die sich nicht um die Modulnamen der anderen kümmern müssen.

Paketbeispiel : Nehmen wir nun an, wir haben den folgenden Ordner und die folgenden Dateien. Hier ist mymodule.py identisch mit zuvor und __init__.py ist eine leere Datei:

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

Die Dateien __init__.py sind erforderlich, damit Python die Verzeichnisse als Pakete enthaltend behandelt. Weitere Informationen finden Sie unter dem Link zur Dokumentation der Module, der später bereitgestellt wird.

Unser aktuelles Arbeitsverzeichnis befindet sich eine Ebene über dem normalen Ordner namens mypackage

$ ls
mypackage

Wenn wir jetzt den Python3-Interpreter ausführen, können wir das Modul mymodule.py, das die erforderliche Funktion myfunc enthält, auf folgende Weise importieren und ausführen (normalerweise wählen Sie einfach eine der folgenden Optionen ):

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

Unter der Annahme von Python 3 gibt es eine hervorragende Dokumentation unter: Module

In Bezug auf Namenskonventionen für Pakete und Module sind die allgemeinen Richtlinien in PEP-0008 enthalten - siehe Paket- und Modulnamen

Module sollten kurze Namen in Kleinbuchstaben haben. Unterstriche können im Modulnamen verwendet werden, wenn dies die Lesbarkeit verbessert. Python-Pakete sollten auch kurze Namen in Kleinbuchstaben enthalten, obwohl von der Verwendung von Unterstrichen abgeraten wird.

arcseldon
quelle
5
Schöne einfache Erklärung. Was ist, wenn Sie einen anderen Ordner in mypackage behalten möchten?
Anuj Gupta
3
Das Include hängt völlig davon ab, was Sie geschrieben haben. Wenn Sie Dinge außerhalb einer Funktion auf Ihrem Modul platzieren, werden Sie sie beim Aufrufen von like auslösen import mypackage. Wenn Sie nur eine Funktion aus einem Modul (sogar einer Datei) importieren möchten, ist dies besser zu verwenden from module import function. In dem Fall ein Unterordner, from subfolder.module import functionso dass Sie einfach function()ohne Feuer andere Codeteile aufrufen können. Verwenden from module import *Sie es auch nicht, wenn Sie es nicht wirklich brauchen.
m3nda
5
Die Frage ist nur noch, wie ich das Paket dazu bringen kann, alles zu importieren import mypackage. Hinzufügen import mymodulezu __init__.pyfunktioniert nicht ..
576i
Ordentliche Erklärung! Ich habe jedoch die Frage, ob numpy ein Paket ist, wie ich numpy.cos (1) in meinem Interpreter ausführen kann, da dies ein Modulname zu sein scheint, der dazwischen verloren geht. Nein?
user1935724
3
Wie wäre es mit pip?
Whackamadoodle3000
199

Da noch niemand diese Frage des OP behandelt hat:

Was ich machen wollte:

Machen Sie ein Python-Modul mit "pip install ..." installierbar.

Hier ist ein absolut minimales Beispiel, das die grundlegenden Schritte zum Vorbereiten und Hochladen Ihres Pakets auf PyPI mit setuptoolsund zeigt twine.

Dies ist keineswegs ein Ersatz für das Lesen zumindest des Tutorials . Es steckt viel mehr dahinter, als in diesem sehr einfachen Beispiel behandelt wird.

Das Erstellen des Pakets selbst wird hier bereits durch andere Antworten behandelt. Nehmen wir also an, wir haben diesen Schritt und unsere Projektstruktur wie folgt:

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

Um zum setuptoolsVerpacken zu verwenden, müssen wir eine Datei hinzufügen setup.py, die in den Stammordner unseres Projekts verschoben wird:

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

Zumindest geben wir die Metadaten für unser Paket an, unsere setup.pywürden folgendermaßen aussehen:

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

Da wir festgelegt haben, fügen license='MIT'wir eine Kopie in unser Projekt ein LICENCE.txt, zusammen mit einer Readme-Datei in reStructuredText als README.rst:

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

An diesem Punkt können wir mit dem Verpacken beginnen setuptools. Wenn wir es noch nicht installiert haben, können wir es installieren mit pip:

pip install setuptools

Um dies zu tun und einen zu erstellen source distribution, rufen wir in unserem Projektstammordner unseren setup.pyüber die Befehlszeile auf und geben an, dass wir Folgendes möchten sdist:

python setup.py sdist

Dadurch werden unser Distributionspaket und die Ei-Informationen erstellt und eine Ordnerstruktur wie diese erstellt. Unser Paket enthält dist:

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

Zu diesem Zeitpunkt haben wir ein Paket, das wir mithilfe pipunseres Projektstamms installieren können (vorausgesetzt, Sie haben alle Namen wie in diesem Beispiel):

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

Wenn alles gut geht, können wir jetzt einen Python-Interpreter öffnen, würde ich irgendwo außerhalb unseres Projektverzeichnisses sagen, um Verwirrung zu vermeiden, und versuchen, unser glänzendes neues Paket zu verwenden:

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

Nachdem wir bestätigt haben, dass das Paket installiert ist und funktioniert, können wir es auf PyPI hochladen.

Da wir das Live-Repository mit unseren Experimenten nicht verschmutzen möchten, erstellen wir ein Konto für das Test-Repository und installieren es twinefür den Upload-Prozess:

pip install twine

Jetzt sind wir fast da. Nachdem unser Konto erstellt wurde, werden wir einfach twineaufgefordert, unser Paket hochzuladen. Es fragt nach unseren Anmeldeinformationen und lädt unser Paket in das angegebene Repository hoch:

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

Wir können uns jetzt in unser Konto im PyPI-Test-Repository einloggen und unser frisch hochgeladenes Paket eine Weile bestaunen und es dann mit pipfolgenden Informationen abrufen :

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

Wie wir sehen können, ist der grundlegende Prozess nicht sehr kompliziert. Wie ich bereits sagte, steckt viel mehr dahinter als hier beschrieben. Lesen Sie also das Tutorial, um eine ausführlichere Erklärung zu erhalten.

bgse
quelle
Wird mein Paket gleich danach veröffentlicht setuptools?
U10-Forward
@ U9-Forward Nein, die Veröffentlichung ist abgeschlossen twine, aber Sie können Ihr Paket vor dem Veröffentlichen lokal testen, nachdem Sie es mit erstellt haben setuptools.
Bgse
9

Nachdem Sie die von Ihnen ausgewählten Befehle definiert haben, können Sie die gespeicherte Datei einfach per Drag & Drop in den Lib-Ordner in Ihren Python-Programmdateien ziehen.

>>> import mymodule 
>>> mymodule.myfunc()
Dreamatronix
quelle
2

Erstellen Sie eine Datei mit dem Namen "hello.py".

Wenn Sie Python 2.x verwenden

def func():
    print "Hello"

Wenn Sie Python 3.x verwenden

def func():
    print("Hello")

Führen Sie die Datei aus. Dann können Sie Folgendes versuchen:

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

Wenn Sie ein bisschen hart wollen, können Sie Folgendes verwenden:

Wenn Sie Python 2.x verwenden

def say(text):
    print text

Wenn Sie Python 3.x verwenden

def say(text):
    print(text)

Sehen Sie die in der Klammer neben der Definition? Das ist wichtig. Es ist dasjenige, das Sie innerhalb der Definition verwenden können.

Text - Sie können ihn verwenden, wenn das Programm sagen soll, was Sie wollen. Nach seinem Namen ist es Text. Ich hoffe du weißt was Text bedeutet. Es bedeutet "Wörter" oder "Sätze".

Führen Sie die Datei aus. Wenn Sie Python 3.x verwenden, können Sie Folgendes versuchen:

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

Für Python 2.x - denke ich dasselbe mit Python 3? Keine Ahnung. Korrigieren Sie mich, wenn ich in Python 2.x einen Fehler gemacht habe (ich kenne Python 2, werde aber mit Python 3 verwendet)

Kakkoiikun
quelle
2

Ich habe ein Projekt erstellt, um ein Projektskelett einfach von Grund auf neu zu initiieren . https://github.com/MacHu-GWU/pygitrepo-project .

Sie können beispielsweise ein Testprojekt erstellen learn_creating_py_package.

Sie können lernen, welche Komponente Sie für verschiedene Zwecke haben sollten, wie zum Beispiel :

  • virtualenv erstellen
  • installieren Sie sich
  • lauf unittest
  • Codeabdeckung ausführen
  • Dokument erstellen
  • Dokument bereitstellen
  • Führen Sie unittest in einer anderen Python-Version aus
  • Bereitstellung auf PYPI

Der Vorteil der Verwendung pygitrepoist , dass diese mühsame erstellt sich automatisch und passen Sie Ihre package_name, project_name, github_account, document host service, windows or macos or linux.

Es ist ein guter Ort, um zu lernen, wie man ein Python-Projekt wie ein Profi entwickelt.

Hoffe das könnte helfen.

Vielen Dank.

MacSanhe
quelle