2017-03-13 5 views
3

Die Python Cookbook schlägt folgende Baumstruktur für ein „typisches Bibliothekspaket“:Wie fügt man Beispiele oder Testprogramme in ein Paket ein?

projectname/ 
    README.txt 
    Doc/ 
     documentation.txt 
    projectname/ 
     __init__.py 
     foo.py 
     bar.py 
     utils/ 
      __init__.py 
      spam.py 
      grok.py 
    examples/ 
     helloworld.py 

Sie werden bemerkt, dass die examples/ nicht Teil des eigentlichen Pakets sind, die unter projectname/projectname/ befindet (das ist, wo Sie ' Ich finde die oberste Ebene __init__.py des Pakets).

Nun, examples/helloworld.py muss offensichtlich das projectname Paket importieren.

Ich bin mir bewusst, dass es in StackOverflow mindestens 2-3 relevante Fragen gibt. Ich glaube nicht, dass dies ein Duplikat ist, weil die anderen Fragen entweder Intrapaket-Importe oder den allgemeinen Fall des Imports eines Python-Moduls von einem anderen beinhalten, wenn sie nicht im selben Verzeichnis liegen. Ich frage speziell nach dem vorgeschlagenen Weg, dies beim Verpacken einer Bibliothek zu tun.

Gibt es eine Möglichkeit, dies zu erreichen, ohne den Pfad zu ändern? Wenn nur der Pfad geändert werden kann, gibt es einen Weg, dies auf elegante Weise zu tun?

Lassen Sie mich auf diesen letzten Punkt näher eingehen. In Repository Structure and Python von Kenneth Reitz erscheint eine ähnliche Struktur mit tests/ anstelle von examples/. Das ist genau das gleiche Problem. Er schlägt vor, "eine einfache (aber explizite) Pfadänderung zu verwenden, um das Paket richtig aufzulösen." OK, aber das ist der eigentliche Code:

import os 
import sys 
sys.path.insert(0, os.path.abspath('..')) 

ich den .. Teil wirklich nicht mag. Ich hoffe auf eine allgemeinere Lösung, hoffentlich eine, die von dem Verzeichnis funktionieren würde, das ich wählen würde, um das Beispiel (oder den Test) auszuführen.

+0

Sie meinen, anders als einen relativen Pfad in einem Import zu verwenden oder das zu importierende Modul explizit zu übergeben? Wenn Projektname ein Paket ist, können Sie es immer nur explizit importieren, nachdem es installiert wurde. In Tests ist dies normalerweise das, was Sie tun. Fehle ich etwas in deiner Frage? – nir0s

+0

Wie funktioniert "Verwenden eines relativen Pfads in einem Import oder explizites Übergeben des zu importierenden Moduls"? Was wäre die Importlinie für zum Beispiel '' examples/helloworld.py''? Weil ich nicht in der Lage war, es zum Laufen zu bringen ... Was den anderen Vorschlag betrifft, erwähnt Kenneth Reitz auch "Erwarten Sie, dass das Paket in den Aufstellungsortpaketen installiert wird" als eine Alternative, aber widerspricht es. –

+0

Ich muss dann falsch verstanden werden. Sie möchten etwas aus 'Beispielen' importieren? Wenn ja, warum ist es kein Paket? – nir0s

Antwort

1

Während der Ordnerstruktur in Ordnung aussieht, glaube ich, dass implizit vorausgesetzt, dass Module für den Import verfügbar sind, sowohl aus der Perspektive eines Entwicklers als auch aus der Sicht eines Benutzers falsch ist.

Es ist wahr, dass Sie technisch sys.path.insert(0, os.path.abspath('..')) verwenden können, um einen beliebigen Pfad für Python hinzuzufügen, um Importe zuzulassen, aber das bedeutet, dass Sie als Entwickler sicherstellen müssen, dass der hinzugefügte Pfad immer an der richtigen Position ist.

Es ist üblich, dass Benutzer Pakete installieren, um sie zu verwenden. Es gibt einen klaren Workflow für Entwickler:

  1. haben pip und virtualenv installiert ist (und noch besser, virtualenvwrapper)
  2. Installieren Sie das Paket in editierbaren Modus des pip -e Flag verwendet, was bedeutet, dass alle Änderungen am Code vornehmen wird direkt Effektausführung. Sie müssen nicht jedes Mal neu installieren, wenn Sie Änderungen an Ihrem Code vornehmen.
  3. Da Ihr Code immer installiert ist (speziell unter site-packages als Benutzer, aber im bearbeitbaren Modus, wenn Sie entwickeln), können Sie Ihr Paket immer mit seinem expliziten Namen aus einem beliebigen Beispiel oder Test importieren.

Ein gemeinsamer Workflow:

$ pip install virtualenv 
... 
$ virtualenv distro 
New python executable in /home/nir0s/work/distro/bin/python3 
Also creating executable in /home/nir0s/work/distro/bin/python 
Installing setuptools, pip, wheel...done. 

$ source distro/bin/activate 

# install in editable mode 
$ pip install -e ~/repos/nir0s/distro/ 
Obtaining file:///home/nir0s/repos/nir0s/distro 
Installing collected packages: distro 
    Running setup.py develop for distro 
Successfully installed distro 

(distro) $ pip freeze 
appdirs==1.4.3 
-e [email protected]:nir0s/[email protected]#egg=distro 
packaging==16.8 
pyparsing==2.2.0 
six==1.10.0 

Das Paket, in editierbaren Modus installiert wird, bedeutet, dass es eine Ei-Link-Datei in das Verzeichnis des Pakets zeigt:

$ cat distro/lib/python3.6/site-packages/distro.egg-link 
/home/nir0s/repos/nir0s/distro 

Benutzer wird dasselbe tun, ohne sich mit dem bearbeitbaren Modus zu beschäftigen. Erstellen Sie einfach virtuelle Umgebungen und installieren Sie Pakete in ihnen. Wenn sie fertig sind, löschen sie diese virtuellen Umgebungen. Kinderleicht.

Verwandte Themen