2013-07-03 3 views
14

Sono nuovo di zecca nella gestione dei pacchetti Python e sicuramente ho fatto qualcosa di sbagliato. Sono stato incoraggiato a creare una struttura di directory come segue:Come strutturare i pacchetti Python senza ripetere il nome di livello superiore per l'importazione

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

bagoftricks.py contiene due funzioni, levenshtein() e geofind().

vorrei chiamare questi come:

import bagoftricks 

x = bagoftricks.levenshtein(arg1,arg2) 

Invece, trovo che devo fare questo:

import bagoftricks 

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

C'è un modo migliore per organizzare i miei pacchetti, in primo luogo, senza la ridondanza di denominazione?

UPDATE

Così, ho seguito le istruzioni del Avichal Badaya qui sotto, e rimosso un livello di nidificazione. Cioè, ora ho ...

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

Tuttavia, per chiamare questo pacchetto, ho ancora ...

from bagoftricks.bagoftricks import geofind() 

o

import bagoftricks 

poi

>>> bagoftricks.bagoftricks.geofind() 

Piuttosto che il desiderato ....

from bagoftricks import geofind() 

o

import bagoftricks 

>>> bagoftricks.geofind() 

non posso rimuovere questo ulteriore livello di nidificazione. Quando provo, per analogia, di rimuovere più di un livello di nidificazione, in modo che il mio modulo è piatta, come:

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

non riesco a compilare il pacchetto a tutti ...

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

Qual è la segreto per le importazioni naturali come i pacchetti standard utilizzati, senza importazioni di nomi di livello superiore ridondanti?

risposta

20

Il primo livello "bagoftricks" va bene. Questo è solo il nome del tuo "progetto", per così dire. In hai un setup.py e altri file che dicono ai sistemi di imballaggio cosa devono sapere.

È quindi possibile avere il codice direttamente in questo modulo o in una directory src. Si può anche andare, per quanto solo avere questa struttura:

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

ma non vorrei raccomandare che, soprattutto perché si potrebbe desiderare di riorganizzare le cose in seguito, ed è più facile se si dispone già di un pacchetto "corretto". Inoltre, molte persone, strumenti e documenti presumono che tu abbia un pacchetto, quindi è più facile.

Così il minimo sarebbe:

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

Con __init__.py contenente le funzioni che si desidera importare. È quindi utilizzare queste funzioni in questo modo:

from bagoftricks import levenshtein, anotherfunction 

Una volta che __init__.py diventa troppo grande, si vuole dividerlo in diversi moduli, offrendo qualcosa di simile:

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

tuo __init__.py dovrebbe quindi importare le funzioni dei vari moduli:

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

E quindi puoi ancora usarli come hai fatto prima.

+0

Grazie, questo è chiaro e utile, specialmente il consiglio su come far crescere in modo efficace e corretto. Il problema era quindi la mia dichiarazione __init__.py. Non ho capito bene dove si trovava nella gerarchia e dove metterlo per abbreviare la chiamata. Funziona perfettamente. Grazie! – Mittenchops

1

Segui seguente struttura:

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

e allora si dovrebbe essere in grado di usarlo come:

from bagoftricks.bagoftricks import levenshtein, geofind 

ma dopo aver apportato la modifica nella struttura delle cartelle fare: -

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

e reinstallare il pacchetto

nel frattempo verifica la configurazione.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(), 
) 

l'installazione potrebbe avere anche altri parametri. Spero che funzioni per te.

+0

Is c'è qualche configurazione che mi permetterebbe di farlo con una singola chiamata? Proprio da bagoftricks import levenshtein, geofind' invece della chiamata del sottomodulo, 'from bagoftricks.bagoftricks import levenshtein, geofind'? – Mittenchops

+0

@Mittenchops metti 'da. bagoftricks importa levenshtein, geofind' nel tuo 'bagoftricks/__ init __. py' – amigcamel

1

con la struttura aggiornata che hai postato

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 un programma diverso che si può fare il follwing

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

nota che è possibile importare anche una wild card

from bagoftricks import * 
+0

Sebbene l'importazione di caratteri jolly come "from module import *" sia considerata una pratica molto negativa, perché può causare conflitti nello spazio dei nomi. Cerca sempre di importare nominando tutto ciò che importi. – kramer65

+0

sì - hai ragione ma per questo esempio va bene - nota anche che i moduli di bagoftricks vengono importati nel namespace bagoftricks. – silviud

+0

Solo chiedendo; perché va bene per questo esempio? Se importi geofind da bagoftricks dopo di che importi una funzione chiamata anche geofind da un altro modulo, hai un conflitto. Cosa mi manca qui? Perché questo esempio è diverso rispetto ad altri codici Python? L'importazione con caratteri jolly è una cattiva pratica, punto. – kramer65