Wir planen, diesen Sommer einen Praktikanten zu haben, aber sie haben noch nie ein Paket gemacht.
Wenn Sie es jedoch als Unternehmen nicht verpacken, wird es einige Zeit dauern, es in der Praxis einzusetzen, was schwierig ist.
Daher habe ich ein Dokument "Wie erstelle ich ein Python-Paket" für den internen Gebrauch geschrieben. Lassen Sie den Praktikanten dies lesen und machen Sie ein schönes Paket! Es ist ein bequemer Plan.
Ich habe das Verpackungs-Know-how jedoch nicht richtig und systematisch studiert und mache mir deshalb Sorgen. Also beschloss ich, ein Gedicht über Qiita zu veröffentlichen und das Gedicht korrigieren zu lassen.
Bitte verzeihen Sie, dass Japanisch an einigen Stellen seltsam ist. Ich bin auf Japanisch unbequem. [^ 1]
Mit anderen Worten, es ist das vorausgesetzte Wissen, über das der Praktikant verfügt.
↓ Gedicht von hier
Tatsächlich gibt es in der Python-Welt keine offizielle Verzeichnisstruktur. Der Code funktioniert auch, wenn Sie eine schlampige Verzeichnisstruktur haben. Dies würde den Code jedoch für andere Entwickler sehr verwirrend machen. Deshalb brauchen wir eine leicht verständliche Verzeichnisstruktur.
Ich empfehle daher, der Methode [dieses Blogs] zu folgen (http://docs.python-guide.org/en/latest/writing/structure/). Dieser Blog klont das Github Repository. Lassen Sie uns dieses Repository erneut klonen.
MacBook-Pro% git clone [email protected]:kennethreitz/samplemod.git
Die Paketbenennungskonvention von Python lautet __ alle niedrigeren Ränge __ und __ durch Unterstriche getrennt __ wird empfohlen. Googles großartige Leute und [Leute in Python](https://www.python.org/dev/peps/ pep-0008 / # Paket- und Modulnamen) sagt dies, daher ist es sicherer, zu folgen.
Dieses Mal erstellen wir ein Paket mit dem Namen "hoge_hoge". Es ist eine gute Idee, das geklonte Verzeichnis mit dem Paketnamen abzugleichen.
Das geklonte Verzeichnis enthält auch die ursprüngliche Git-Datei. Löschen wir also zuerst die Git-Datei.
Stellen Sie danach das Verzeichnis, in dem sich das Skript befindet, auf den Paketnamen ein. Mit anderen Worten, es ist hoge_hoge
.
MacBook-Pro% mv samplemod hoge_hoge
MacBook-Pro% cd hoge_hoge
MacBook-Pro% rm -rf .git
MacBook-Pro% mv sample hoge_hoge
Nachdem Sie den obigen Befehl ausgeführt haben, sollte Ihre Verzeichnisstruktur folgendermaßen aussehen.
(In Reaktion auf den Vorschlag von @ shn geändert. Requirement.txt
wurde gelöscht.)
MacBook-Pro% tree
.
├── LICENSE
├── Makefile
├── README.rst
├── docs
│ ├── Makefile
│ ├── conf.py
│ ├── index.rst
│ └── make.bat
├── hoge_hoge
│ ├── __init__.py
│ ├── core.py
│ └── helpers.py
├── setup.py
└── tests
├── __init__.py
├── context.py
├── test_advanced.py
└── test_basic.py
Lassen Sie uns einen neuen Git für Ihr nächstes Paket initialisieren.
MacBook-Pro% git init
MacBook-Pro% git add .
MacBook-Pro% git commit -m 'first commit'
Sie sind jetzt bereit.
Es gibt verschiedene Tools, die die Verzeichnisstruktur von Python-Paketen initialisieren. Cookiecutter. Aber ich empfehle es nicht sehr. Dies liegt daran, dass zu viele zusätzliche Dateien erstellt werden.
setup.py
ist eine erforderliche Datei für das Paket. Schreiben Sie in diese Datei die Abhängigkeitsinformationen, Versionsinformationen und den Paketnamen des zu erstellenden Pakets.
Dieses Gedicht beschreibt nur die Mindestfelder. Wenn Sie sich für andere Bereiche interessieren, lesen Sie Die Schriften der Menschen in Python.
Der Inhalt der ursprünglichen setup.py
sollte so aussehen.
setup(
name='sample',
version='0.0.1',
description='Sample package for Python-Guide.org',
long_description=readme,
author='Kenneth Reitz',
author_email='[email protected]',
url='https://github.com/kennethreitz/samplemod',
license=license,
packages=find_packages(exclude=('tests', 'docs'))
)
Feldname | Erläuterung | Detailliertere Erklärung |
---|---|---|
name | Schreiben Sie den Namen des Pakets | |
version | Schreiben Sie die aktuellen Versionsinformationen | |
description | Lassen Sie uns kurz schreiben "Was macht dieses Paket?" | |
install_requires | Schreiben Sie abhängige Paketinformationen | Dies |
dependency_links | Schreiben Sie, wenn das abhängige Paket in pypi nicht vorhanden ist. | Dies |
__ Insbesondere ist das, was Sie unbedingt schreiben müssen, install_requires
. Entwickler, die Ihre Pakete verwenden, wissen nicht, von welchem Paket Sie abhängig sind. Ohne diese Informationen werden andere Entwickler in Schwierigkeiten geraten.
(Dependency_links
wird von [pip update] um 2019/1 entfernt (https://github.com/pypa/pip/pull/6060). Alternative Methoden werden später beschrieben.)
Vielleicht haben Sie schon einmal python setup.py install
gemacht. Dieser Befehl funktioniert, weil die Abhängigkeitsinformationen ordnungsgemäß geschrieben wurden.
Beschreiben Sie die Pakete, die von der Liste abhängen, im Feld "install_requires". Wenn Sie beispielsweise "numpy" benötigen, schreiben Sie "numpy".
setup(
name='sample',
version='0.0.1',
description='Sample package for Python-Guide.org',
long_description=readme,
author='Kenneth Reitz',
author_email='[email protected]',
install_requires=['numpy'],
url='https://github.com/kennethreitz/samplemod',
license=license,
packages=find_packages(exclude=('tests', 'docs'))
)
Wenn Sie ein allgemeines Unternehmen sind, betreiben Sie wahrscheinlich ein Paket, das Sie selbst entwickelt haben. Es gibt kein solches Paket in Pypi, daher müssen Sie setup.py mitteilen, wo sich das Paket befindet. dependency_links
wird zu solchen Zeiten benötigt.
Möglicherweise möchten Sie "dependency_links" in Zukunft nicht mehr verwenden. Der Grund ist, dass dependency_links
in pip veraltet ist.
Eine Alternative besteht darin, es in die Datei resources.txt zu schreiben.
require.txt
wird seit langem von install_requires
als alternative paketabhängige Beschreibung verwendet.
Es ist eine egoistische Meinung, aber ich denke, es ist eine ziemlich verbreitete Methode.
Beschreiben Sie die Abhängigkeitsinformationen in require.txt
wie folgt.
#Sie können den in pypi vorhandenen Paketnamen so schreiben, wie er ist
numpy
#Verwenden Sie eine Gleichung, wenn Sie die Version angeben möchten
scipy == 1.2.2
#git für Pakete, die in pypi nicht existieren://Repository-URL.git
git://[email protected]/foo/foo.git
#Für private Repositories+Fügen Sie ssh git hinzu+ssh://[email protected]/foo/foo.git
git+ssh://[email protected]/foo/foo.git
Schreiben Sie dann den Prozess zum Lesen von require.txt in setup.py.
Dieser Code ist genau richtig.
import os, sys
from setuptools import setup, find_packages
def read_requirements():
"""Parse requirements from requirements.txt."""
reqs_path = os.path.join('.', 'requirements.txt')
with open(reqs_path, 'r') as f:
requirements = [line.rstrip() for line in f]
return requirements
setup(
..., # Other stuff here
install_requires=read_requirements(),
)
(Wichtig) Diese Geschichte ist zumindest auf pip nicht mehr verfügbar. setuptools könnte dieses Argument bald entfernen. Bitte halten Sie es daher für veraltet.
(Im Fall von Hayashi) Da ich Github verwende, werde ich nur das Beispiel von Git schreiben. Für andere Versionsverwaltungssysteme StackOverFlow-Artikel Mal sehen.
Die Grundformel lautet
git+ssh://git@URL-TO-THE-PACKAGE#egg=PACKAGE-NAME
ist. Angenommen, Sie möchten Abhängigkeitsinformationen für ein Paket namens "unko" schreiben. Zu jener Zeit
git+ssh://[email protected]/our-company-internal/unko.git#egg=unko
ist. Wenn Sie das Problem in einer bestimmten Version beheben möchten, können Sie den Zweig- oder Tag-Namen nach "@" angeben.
git+ssh://[email protected]/our-company-internal/[email protected]#egg=unko-0.1
@ v0.1
ist der Filialname oder Tag-Name von github. -0.1
ist die Paketversion.
Schreiben Sie abschließend die Informationen wie "Name", "Autor" neu. Wenn Sie Ihren Namen schreiben, werden Sie wahrscheinlich daran angehängt;)
Die endgültige setup.py
sieht so aus.
import os, sys
from setuptools import setup, find_packages
def read_requirements():
"""Parse requirements from requirements.txt."""
reqs_path = os.path.join('.', 'requirements.txt')
with open(reqs_path, 'r') as f:
requirements = [line.rstrip() for line in f]
return requirements
setup(
name='hoge_hoge',
version='0.0.1',
description='Sample package for Python-Guide.org',
long_description=readme,
author='Kensuke Mitsuzawa',
author_email='[email protected]',
install_requires=read_requirements(),
url='https://github.com/kennethreitz/samplemod',
license=license,
packages=find_packages(exclude=('tests', 'docs'))
)
Es gibt viele Möglichkeiten, Code zu schreiben, aber ich werde diesmal nicht auf Details eingehen. Bitte schreiben Sie wie zuvor. Aber [__ "Woran ich mich erinnern soll" __](http://qiita.com/Kensuke-Mitsuzawa/items/7717f823df5a30c27077#%E8%A6%9A%E3%81%88%E3%81%A6% E3% 81% 8A% E3% 81% 84% E3% 81% A6% E3% 81% BB% E3% 81% 97% E3% 81% 84% E3% 81% 93% E3% 81% A8) Deshalb will ich es.
Stellen Sie sicher, dass Sie den Test schreiben. Vielleicht haben Sie den Code geschrieben, um den Vorgang zuvor zu überprüfen. Berücksichtigen Sie jedoch zusätzlich zur Überprüfung des Betriebs den Testfall so weit wie möglich selbst und überprüfen Sie die Ausgabe.
Hier erklären wir nur, wie man einen Testfall schreibt. In Python gibt es ein Standard-Testframework namens "unittest". Verwenden wir dieses Framework. Ich werde die Details weglassen, aber siehe Dieser Artikel-JP und Dieser Artikel-DE. Lassen Sie uns beherrschen, wie man es benutzt.
Der Ort, an dem der Testcode abgelegt werden kann, befindet sich im Verzeichnis tests /
.
├── setup.py
└── tests
├── __init__.py
├── context.py
├── test_advanced.py
└── test_basic.py
Wenn Sie ein Modulskript für das Paket erstellen, erstellen wir ein Testskript. Auf diese Weise können Sie die Korrespondenz klar sehen und die Wartung ist einfacher. Angenommen, Sie haben "hoge_hoge / core.py" als Modulskript erstellt.
├── hoge_hoge
│ ├── __init__.py
│ ├── core.py
Platzieren Sie das Testskript für core.py
unter tests /
. Es ist einfacher zu verstehen, wenn Sie das Präfix "test_" zu "test_core.py" hinzufügen.
└── tests
├── __init__.py
├── test_core.py
Beim Schreiben eines Testskripts sind zwei Dinge zu beachten.
test_
wird vor dem Methodennamen benötigt. Ohne dieses Präfix würde der Test ignoriert.Lassen Sie uns nach dem Testen das Skript ausführen. python test_core.py
.
Oder wenn es pycharm ist, drücken Sie die normale Ausführtaste und der Test wird ausgeführt.
import unittest
class TestCore(unittest.TestCase):
@classmethod
def setUpClass(cls):
# procedures before tests are started. This code block is executed only once
pass
@classmethod
def tearDownClass(cls):
# procedures after tests are finished. This code block is executed only once
pass
def setUp(self):
# procedures before every tests are started. This code block is executed every time
pass
def tearDown(self):
# procedures after every tests are finished. This code block is executed every time
pass
def test_core(self):
# one test case. here.
# You must “test_” prefix always. Unless, unittest ignores
pass
if __name__ == '__main__':
unittest.main()
(Aktualisiert als Antwort auf @ podhmos Kommentar. Danke!)
Nachdem Sie einige Testskripte geschrieben haben, können Sie python setup.py test
ausführbar machen.
Stellen Sie sicher, dass Sie die Gewohnheit haben, diesen Befehl auszuführen, wenn Sie größere Änderungen vornehmen. Ich finde oft Probleme, die ich nicht im Kopf habe. Wenn ich an der Verbesserung des Pakets arbeite, vergesse ich oft, den Test auszuführen, indem ich ihn in "Oh, ändere das auch" ändere.
Dies ist auch sehr hilfreich, da andere Entwickler es problemlos in ihrer eigenen Umgebung testen können.
Das aktuelle Testverzeichnis hat diese Struktur.
└── tests
├── __init__.py
├── test_all.py
├── test_advanced.py
└── test_basic.py
Geben Sie den Speicherort des Testverzeichnisses in setup.py an. setup.py lädt automatisch die Testklasse und führt den Test für Sie aus.
setup(
name='hoge_hoge',
version='0.0.1',
description='Sample package for Python-Guide.org',
long_description=readme,
author='Kensuke Mitsuzawa',
author_email='[email protected]',
install_requires=['numpy', 'unko'],
dependency_links=['git+ssh://[email protected]/our-company-internal/unko.git#egg=unko'],
url='https://github.com/kennethreitz/samplemod',
license=license,
packages=find_packages(exclude=('tests', 'docs')),
test_suite='tests'
)
Führen Sie python setup.py test
aus. Sie können sehen, wie alle Tests ausgeführt werden.
Wenn ein Fehler auftritt, wird er am Ende angezeigt.
Mechanko erstaunlicher Algorithmus kann in Ihrem Paket implementiert werden. Andere Entwickler haben jedoch nicht die Zeit, den Inhalt einzeln zu überprüfen. (Unglücklicherweise)
Die Schnittstelle wird benötigt, um Ihren Mechanko-Algorithmus für Affenentwickler vorzubereiten.
Selbst mit einer einfachen Oberfläche beschweren sich Affenentwickler, dass sie nicht wissen, wie man sie benutzt. Lassen Sie uns einen Beispielcode schreiben und Ihnen den Umgang damit beibringen.
Ich denke, der Ort, an dem die Schnittstelle geschrieben wird, hängt von Ihren Vorlieben ab. Wenn Sie objektorientierten Code schreiben, können Sie Schnittstellenmethoden innerhalb der Klasse schreiben. Wenn Sie ein Funktionsobjekt in eine Skriptdatei wie Python schreiben, können Sie eine Skriptdatei für die Schnittstelle vorbereiten. (Ich bin übrigens der letztere.)
Stellen Sie in jedem Fall sicher, dass __ die Ein- und Ausgabe geklärt ist __. Nehmen Sie als Beispiel die Anforderungspaketschnittstelle (https://github.com/kennethreitz/requests/blob/fb014560611f6ebb97e7deb03ad8336c3c8f2db1/requests/api.py). [^ 2]
Das Wichtigste im Beispielcode ist, __ Eingabe / Ausgabe __ zu klären. Affenentwickler kopieren häufig Beispielcode und fügen ihn ein. Der Beispielcode, mit dem Sie die Ein- und Ausgabe auch bei Verwendung der Kopie sofort verstehen können, ist der beste. Als Beispiel wird die Verwendung von jaconv erwähnt.
Wenn Ihr Team einen README-Schreibstil hat, befolgen Sie diesen Stil __. (Leider gibt es in Heisha keine solche Methode)
Das Prinzip beim Schreiben einer README ist, dass "andere Entwickler die Installationsmethode und die Ausführungsmethode nur durch Lesen der README verstehen können".
In den meisten Fällen sollten Sie über die folgenden Informationen verfügen.
python setup.py install
in Ordnung sein)python setup.py test
in Ordnung sein)
--Wie benutzt man es? (Im Allgemeinen sollte "Beispielcode anzeigen" in Ordnung sein.)Wenn Elemente im Voraus vorbereitet werden müssen, müssen sie in die README-Datei geschrieben werden. Zum Beispiel
--Mecab muss im Voraus installiert werden
In einem solchen Fall müssen Sie es in die README schreiben. Wenn Sie es sich leisten können, schreiben Sie eine Datei erstellen. Andere Entwickler weinen und freuen sich.
Eine Sache, die Sie beachten sollten, ist, dass "andere Entwickler die Eingabe und Ausgabe nicht verstehen können, wenn sie sich nur den Code ansehen." Aus diesem Grund benötigen Sie Beispielcode oder müssen sicherstellen, dass Sie Dokumentkommentare haben. Es ist jedoch schwierig, höfliche Kommentare zu allen Methoden und Funktionen zu schreiben (die für einen Praktikanten verfügbare Zeit ist begrenzt). Schreiben Sie zumindest die __ Schnittstellenfunktion Eingabe / Ausgabe __ mit einer höflichen Erklärung.
Verwenden Sie github, um Ihren Code zu verwalten. Daher kann Ihr Paket (zumindest in unserem Unternehmen) bald von anderen Entwicklern verwendet werden.
Deshalb sollten Sie die Bedeutung von Zweig schätzen. In den meisten Fällen ist der "Master" -Zweig die "stabile Version". Die Entwicklungsversion muss in einen anderen Zweig verschoben werden.
Dies ist beispielsweise mein Entwicklungsstil.
--Push to Master bis zur ersten Alpha-Version (geben Sie immer "Dies ist in Entwicklung" am Anfang der README an) --Erstellen Sie nach der Alpha-Version einen weiteren Entwicklungszweig. Der Umgang mit Zweigen folgt dem Git-Flow [^ 3].
git-flow
ist eine Regel, die bestimmt, wie mit Zweigen umgegangen wird. Diese Regel gibt den Teams Flexibilität bei der Entwicklung.
Folgen Sie git-flow, auch wenn Sie sich selbst entwickeln. Dies liegt daran, dass andere Entwickler reibungslos an der Entwicklung teilnehmen können. Informationen zum Fluss von Git-Flow finden Sie unter Dieser gute Artikel.
Machen Sie dasselbe für andere Entwickler, um die gleichen Ergebnisse zu erzielen. Verwenden Sie keine Hardcode-Informationen, die nur in Ihrer Umgebung ausgeführt werden können. Allgemeine fest codierte Informationen
--Unix-Befehlsausführungspfad
Wenn diese Informationen fest codiert sind, können sie nicht von anderen Entwicklern ausgeführt werden. Ich bin in Schwierigkeiten. Zum Beispiel ist hier ein schlechtes Beispiel
def do_something():
path_to_external_unix_command = '/usr/local/bin/command'
path_to_input_file = '/Users/kensuke-mi/Desktop/codes/hoge_hoge/input.txt'
return call_some_function(path_to_input_file)
Der Inhalt von "input.txt" bleibt niemandem bekannt. In diesem Fall ist das gut.
Hier ist ein gutes Beispiel oben.
def do_something(path_to_external_unix_command, path_to_input_file):
return call_some_function(path_to_input_file)
path_to_input_file = './input.txt'
path_to_external_unix_command = load_from_setting_file()
do_something(path_to_external_unix_command, path_to_input_file)
Ich habe mehrmals "klar eingegeben und ausgegeben" geschrieben, aber um ehrlich zu sein, ist es problematisch. Darüber hinaus ist es leicht zu vergessen, wenn Sie es ändern. In diesem Fall ist es nicht sinnvoll, einen klaren Kommentar zu schreiben. Hier ist also der Typhinweis. Es ist ein Mechanismus, der den Typ eines Objekts wie Java beschreiben kann. Der Unterschied zu Java besteht jedoch darin, dass Pythons "Typhinweis keine Auswirkung auf die Ausführung hat". [^ 4]
――Die Anzahl der Eingabezeichen nimmt etwas zu
Ich gebe Ihnen ein Beispiel. Wer sind die "Namen" und "Personen" in dieser Implementierung? Es ist nicht gut verstanden. Und was ist "Begrüßung" eine Funktion, die zurückgibt? Ist auch unbekannt.
def greeting(names, persons):
target = decide_target_person(persons)
greet = generate(target, names)
return greet
Fügen wir hier einen Typhinweis hinzu.
def greeting(names: List[str], persons: Dict[str, str])->str:
target = decide_target_person(persons)
greet = generate(target, names)
return greet
Jetzt sind die Ein- und Ausgänge klar!
Pycharm unterstützt Typhinweise vollständig.
--Vorschlag der Methode, die das Objekt hat
Das Bild unten ist der Entwicklungsbildschirm von Pycharm. Ich erhalte eine Warnung, weil ich bei der Eingabe und Ausgabe von "Ziel" einen Fehler gemacht habe.
Dieser Bereich ist ein guter Artikel.
In Python2 kann der Typhinweis des Python3-Ausdrucks nicht interpretiert werden, und es tritt ein Fehler auf. PEP bietet jedoch eine großartige Möglichkeit, "einen Typhinweis als Kommentar zu schreiben". Pycharm wird noch nur teilweise unterstützt, sollte aber in naher Zukunft vollständig unterstützt werden.
↑ Bisher Gedicht
Es fühlt sich chaotisch an, aber ist es okay? Ist es möglich, ein Paket nur mit solchen Informationen zu erstellen? Ich bin besorgt. Tsukkomi ist willkommen.
[^ 1]: Eigentlich ist das Originaldokument selbst in Englisch geschrieben. Einige internationale Studierende kommen zum Praktikanten. [^ 2]: Das Anforderungspaket hat den Ruf, "sehr einfach zu lesender Code" zu sein. [^ 3]: Eigentlich ist "Git-Flow" der Name des Tools, aber es zeigt oft den Entwicklungsstil an (nur um mich herum ??) [^ 4]: Ist das nicht gegen Pythons Philosophie? Ich höre ein paar Stimmen sagen, aber es ist ein Punkt, der im PEP "Akzeptiert" ist, wo Leute in Python aktiv sind. Daher gibt es einige Dinge, die Sie behalten sollten. (Erstens ist das Mitglied, das diesen Vorschlag gemacht hat, Guido van Rossum)
Recommended Posts