2013-07-03 2 views
14

Ich bin brandneu bei Python-Paket-Management, und sicherlich etwas falsch gemacht haben. Ich wurde aufgefordert, eine Verzeichnisstruktur zu erstellen, wie folgt:Wie Python-Pakete zu strukturieren, ohne Top-Level-Namen für den Import zu wiederholen

bagoftricks 
├── bagoftricks 
│   ├── bagoftricks 
│   │   ├── __init__.py 
│   │   └── bagoftricks.py 
│   └── __init__.py 
├── README.md 
└── setup.py 

bagoftricks.py enthält zwei Funktionen, levenshtein() und geofind().

würde ich diese als nennen mag:

import bagoftricks 

x = bagoftricks.levenshtein(arg1,arg2) 

Stattdessen finde ich, ich habe dies zu tun:

import bagoftricks 

x = bagoftricks.bagoftricks.levenshtein(arg1,arg2) 

Gibt es eine bessere Art und Weise meine Pakete in erster Linie zu organisieren, ohne die Namensredundanz?

UPDATE

So folgte ich Avichal Badaya die nachstehenden Anweisungen, und entfernt eine Ebene der Verschachtelung. Das heißt, die ich jetzt habe ...

bagoftricks 
├── bagoftricks 
│   ├── __init__.py 
│   └── bagoftricks.py 
├── README.md 
└── setup.py 

jedoch, dieses Paket zu nennen, habe ich noch ...

from bagoftricks.bagoftricks import geofind() 

oder

import bagoftricks 

dann

>>> bagoftricks.bagoftricks.geofind() 

Statt der gewünschten ....

from bagoftricks import geofind() 

oder

import bagoftricks 

>>> bagoftricks.geofind() 

kann ich nicht, dass zusätzliche Schicht der Verschachtelung entfernen. Wenn ich versuche, durch Analogie, eine weitere Ebene der Verschachtelung zu entfernen, so dass mein Modul flach ist, wie:

bagoftricks 
├── __init__.py 
├── bagoftricks.py 
├── README.md 
└── setup.py 

ich überhaupt das Paket nicht bauen kann ...

$ python setup.py build 
running build 
running build_py 
error: package directory 'bagoftricks' does not exist 

Was das ist Geheimnis für natürliche Importe wie Standard-Pakete verwenden, ohne redundante Top-Level-Namen importiert?

Antwort

20

Die erste Ebene "bagoftricks" ist in Ordnung. Das ist sozusagen der Name Ihres "Projekts". Sie haben eine setup.py und andere Dateien, die den Verpackungssystemen mitteilen, was sie wissen müssen.

Sie können den Code dann direkt in diesem Modul oder in einem src-Verzeichnis haben.

bagoftricks 
├── bagoftricks.py 
├── README.md 
└── setup.py 

Aber ich würde das nicht empfehlen, vor allem, weil Sie später Dinge neu organisieren möchtet, und es ist einfacher, wenn Sie bereits ein „richtiges“ Paket haben: Sie können sogar so weit, nur mit dieser Struktur gehen. Auch die meisten Leute, Tools und Dokumente gehen davon aus, dass Sie ein Paket haben, also ist es einfacher.

So würde das Minimum sein:

bagoftricks 
├── bagoftricks 
│ └── __init__.py 
├── README.md 
└── setup.py 

Mit __init__.py die Funktionen enthält, die Sie importieren möchten. Anschließend verwenden Sie diese Funktionen wie folgt aus:

from bagoftricks import levenshtein, anotherfunction 

Sobald das __init__.py zu groß wird, Sie wollen, dass es in mehreren Modulen aufzuteilen, können Sie so etwas wie dieses geben:

bagoftricks 
├── bagoftricks 
│ ├── __init__.py 
│ ├── anothermodule.py 
│ └── levenshtein.py 
├── README.md 
└── setup.py 

Ihre __init__.py sollte dann importieren Die Funktionen der verschiedenen Module:

from bagoftricks.levenshtein import levenshtein 
from bagoftricks.anothermodule import anotherfunction 

Und dann können Sie sie immer noch wie Sie zuvor verwenden.

+0

Danke, das ist klar und hilfreich, vor allem der Tipp, wie man es effektiv und richtig anbaut. Das Problem war definitiv meine __init__.py Aussage. Ich habe nicht ganz verstanden, wo es in der Hierarchie stand und wo man es hinstellte, um den Anruf zu verkürzen. Funktioniert perfekt. Vielen Dank! – Mittenchops

1

Folgen folgende Struktur:

bagoftricks 
    ── bagoftricks 
    │ ├── __init__.py 
    │ └── bagoftricks.py 
    ├── README.md 
    └── setup.py 

und dann sollten Sie in der Lage sein, es zu benutzen, wie:

from bagoftricks.bagoftricks import levenshtein, geofind 

aber nachdem Sie die Änderung in der Ordnerstruktur auszukommen: -

pip uninstall <your package name mostly mentioned in setup.py> 

und installieren Sie das Paket

unterdessen überprüfen Sie Ihre Einrichtung.py

#!/bin/env python 
import os.path 
from setuptools import setup, find_packages 

def current_path(file_name): 
    return os.abspath(os.path.join(__file__, os.path.pardir, file_name)) 

setup(
    name = 'bagoftricks', 
    version = '0.1', 
    include_package_data = True, 
    packages=find_packages(), 
) 

Setup könnte auch einige andere Parameter haben. Ich hoffe es funktioniert für dich.

+0

Ist Gibt es irgendeine Konfiguration, die es mir mit einem einzigen Anruf erlauben würde? Nur 'von bagoftricks importieren levenshtein, geofind' anstelle des Submodulaufrufs,' von bagoftricks.bagoftricks importieren levenshtein, geofind'? – Mittenchops

+0

@Mittenchops setzen 'aus. bagoftricks import levenshtein, geofind' in deinem 'bagoftricks/__ init __. py' – amigcamel

1

mit der aktualisierten Struktur geschrieben Sie

bagoftricks 
├── bagoftricks 
│ ├── __init__.py 
│ └── bagoftricks.py 
├── README.md 
└── setup.py 

into bagoftricks/__init__.py import all functions that you need 

__init__.py 
from bagoftricks import geofind, levenshtein 

in ein anderes Programm können Sie tun, um die follwing

from bagoftricks import geofind 
import bagoftricks; bagoftricks.geofind(); bagoftricks.bagoftriks.geofind() 

beachten Sie, dass Sie auch eine Wild Card importieren

from bagoftricks import * 
+0

Das Importieren von Wildcards wie 'from module import *' wird jedoch als sehr schlechte Praxis angesehen, da es zu Namespace-Konflikten kommen kann. Versuchen Sie immer zu importieren, indem Sie alles benennen, was Sie importieren. – kramer65

+0

ja - Sie haben recht, aber für dieses Beispiel ist in Ordnung - beachten Sie auch, dass Module aus BagoFtricks in den Namespace bagoftricks importiert werden. – silviud

+0

Ich frage mich nur; Warum ist es in Ordnung für dieses Beispiel? Wenn Sie GeoFind aus BagoFtricks importieren, nach dem Sie eine Funktion namens GeoFind von einem anderen Modul importieren, liegt ein Konflikt vor. Was fehlt mir hier? Warum unterscheidet sich dieses Beispiel von anderem Python-Code? Das Importieren mit Platzhaltern ist eine schlechte Übung, Punkt. – kramer65