Python-Einstiegspunkte erklären?

181

Ich habe die Dokumentation zu den Einstiegspunkten für Eier in Pylons und auf den Peak-Seiten gelesen und verstehe sie immer noch nicht wirklich. Könnte mir jemand sie erklären?

Brad Wright
quelle

Antworten:

168

Ein "Einstiegspunkt" ist normalerweise eine Funktion (oder ein anderes aufrufbares funktionsähnliches Objekt), die ein Entwickler oder Benutzer Ihres Python-Pakets möglicherweise verwenden möchte, obwohl ein nicht aufrufbares Objekt auch als Einstiegspunkt (sowie korrekt) bereitgestellt werden kann in den Kommentaren darauf hingewiesen!).

Die beliebteste Art von Einstiegspunkt ist der Einstiegspunkt console_scripts , der auf eine Funktion verweist, die Sie als Befehlszeilentool für jeden bereitstellen möchten, der Ihr Paket installiert. Dies geht in Ihre setup.py wie folgt:

entry_points={
    'console_scripts': [
        'cursive = cursive.tools.cmd:cursive_command',
    ],
},

Ich habe ein Paket namens "cursive.tools", das ich gerade bereitgestellt habe, und ich wollte, dass es einen "kursiven" Befehl zur Verfügung stellt, den jemand über die Befehlszeile ausführen kann, wie:

$ cursive --help
usage: cursive ...

Der Weg, dies zu tun, besteht darin, eine Funktion zu definieren, wie z. B. eine "cursive_command" -Funktion in cursive / tools / cmd.py, die wie folgt aussieht:

def cursive_command():
    args = sys.argv[1:]
    if len(args) < 1:
        print "usage: ..."

und so weiter; Es sollte davon ausgegangen werden, dass es über die Befehlszeile aufgerufen wurde, die vom Benutzer angegebenen Argumente analysieren und ... nun, alles tun, wofür der Befehl entwickelt wurde.

Installieren Sie das docutils- Paket, um ein hervorragendes Beispiel für die Verwendung am Einstiegspunkt zu erhalten: Es installiert etwa ein halbes Dutzend nützlicher Befehle zum Konvertieren der Python-Dokumentation in andere Formate.

Brandon Rhodes
quelle
3
Die aktuellen Dokumente setup.pyenthalten überhaupt keine entry_points.
Matt Wilkie
2
Dies ist eine hervorragende Antwort, da sie die Leistungsfähigkeit mehrerer Projekte demonstriert, die einen einzigen Gruppennamen für entry_point teilen, nämlich "console_scripts". Vergleichen Sie diese Antwort mit der allgemeineren Antwort von Petri. Sie werden sehen, dass setuptools diesen pkg_resources-Mechanismus verwenden muss, um die console_scripts abzurufen und dann einen Shell-Wrapper um sie herum zu erstellen. Inspirierend? Benutze diese. Sie eignen sich nicht nur für console_scripts.
Bruno Bronosky
188

EntryPoints bieten eine dauerhafte, dateisystembasierte Objektnamenregistrierung und einen namenbasierten direkten Objektimportmechanismus (implementiert vom setuptools- Paket).

Sie verknüpfen Namen von Python-Objekten mit Freiform-IDs. Jeder andere Code, der dieselbe Python-Installation verwendet und den Bezeichner kennt, kann auf ein Objekt mit dem zugehörigen Namen zugreifen, unabhängig davon, wo das Objekt definiert ist. Die zugehörigen Namen können beliebige Namen sein, die in einem Python-Modul vorhanden sind . Zum Beispiel Name einer Klasse, Funktion oder Variablen. Dem Einstiegspunktmechanismus ist es egal, worauf sich der Name bezieht, solange er importierbar ist.

Verwenden wir als Beispiel (den Namen) einer Funktion und eines imaginären Python-Moduls mit dem vollständig qualifizierten Namen 'myns.mypkg.mymodule':

def the_function():
   "function whose name is 'the_function', in 'mymodule' module"
   print "hello from the_function"

Einstiegspunkte werden über eine Einstiegspunktdeklaration in setup.py registriert. So registrieren Sie die Funktion unter dem Einstiegspunkt 'my_ep_func':

    entry_points = {
        'my_ep_group_id': [
            'my_ep_func = myns.mypkg.mymodule:the_function'
        ]
    },

Wie das Beispiel zeigt, werden Einstiegspunkte gruppiert. Es gibt eine entsprechende API, um alle zu einer Gruppe gehörenden Einstiegspunkte nachzuschlagen (Beispiel unten).

Bei einer Paketinstallation (dh dem Ausführen von 'python setup.py install') wird die obige Deklaration von setuptools analysiert. Anschließend werden die analysierten Informationen in eine spezielle Datei geschrieben. Danach kann die pkg_resources-API (Teil von setuptools) verwendet werden, um den Einstiegspunkt nachzuschlagen und auf die Objekte mit den zugehörigen Namen zuzugreifen:

import pkg_resources

named_objects = {}
for ep in pkg_resources.iter_entry_points(group='my_ep_group_id'):
   named_objects.update({ep.name: ep.load()})

Hier lesen setuptools die Einstiegspunktinformationen, die in speziellen Dateien geschrieben wurden. Es fand den Einstiegspunkt, importierte das Modul (myns.mypkg.mymodule) und rief die dort definierte Funktion beim Aufruf von pkg_resources.load () ab.

Angenommen, es gäbe keine anderen Einstiegspunktregistrierungen für dieselbe Gruppen-ID, wäre das Aufrufen der Funktion dann einfach:

>>> named_objects['my_ep_func']()
hello from the_function

Obwohl der Einstiegspunktmechanismus zunächst vielleicht etwas schwer zu erfassen ist, ist er tatsächlich recht einfach zu verwenden. Es bietet ein nützliches Tool für die steckbare Python-Softwareentwicklung.

Petri
quelle
4
Wo wird der Name 'my_ep_func' in all diesen Prozessen verwendet? Es scheint vom pkg_resources-Iterator für nichts verwendet zu werden.
Kamil Kisiel
2
@KamilKisiel: In dem hier zur Veranschaulichung verwendeten Beispiel wird der Name des Einstiegspunkts in der Tat für nichts verwendet und muss es auch nicht sein. Ob der Name des Einstiegspunkts für irgendetwas verwendet wird oder nicht, hängt von der Anwendung ab. Der Name steht einfach als Name - Attribut der Eintrittspunkt - Instanz.
Petri
3
Ich denke, dass das Verwerfen des ep.namens und das Erstellen einer Liste anstelle eines Wörterbuchs mit named_objects verwirrend war, also habe ich die Antwort bearbeitet. Dies ist, was die Antwort zeigt, wo man den Namen bekommt und ob man erwartet, dass er 'the_function' oder 'my_ep_func' ist. Ansonsten musste der Leser an anderer Stelle zusätzliche Unterlagen finden. Dies ist eine AUSGEZEICHNETE Antwort und die kürzeste und klarste Erklärung für Eintrittspunkte, die ich je gesehen habe!
Bruno Bronosky
3
Ich habe ein Projekt auf Github erstellt, das dieses Konzept demonstriert. github.com/RichardBronosky/entrypoint_demo
Bruno Bronosky
1
Dies ist eine sehr klare Erklärung der Einstiegspunkte, die Sie für die ausführliche Erklärung benötigen. Der EntryPointsLink ist veraltet, obwohl die Erklärung sehr klar ist.
Rahul Nair
18

Aus abstrakter Sicht werden Einstiegspunkte verwendet, um eine systemweite Registrierung von Python-Callables zu erstellen, die bestimmte Schnittstellen implementieren. In pkg_resources gibt es APIs, um zu sehen, welche Einstiegspunkte von einem bestimmten Paket angekündigt werden, sowie APIs, um zu bestimmen, welche Pakete einen bestimmten Einstiegspunkt ankündigen.

Einstiegspunkte sind nützlich, damit ein Paket Plugins verwenden kann, die sich in einem anderen Paket befinden. Zum Beispiel Ian Bicking der Paste verwendet Projekt Einspeisepunkten ausgiebig. In diesem Fall können Sie ein Paket schreiben, das die WSGI-Anwendungsfactory über den Einstiegspunkt ankündigt paste.app_factory.

Eine andere Verwendung für Einstiegspunkte ist die Aufzählung aller Pakete auf dem System, die einige Plugin-Funktionen bieten. Das TurboGears- Webframework verwendet den python.templating.enginesEinstiegspunkt, um nach installierten und verfügbaren Vorlagenbibliotheken zu suchen.

Rick Copeland
quelle