2013-07-03 5 views
14

Jestem zupełnie nowy w zarządzaniu pakietami Pythona i na pewno zrobiłem coś złego. I był zachęcany do tworzenia struktury katalogów w następujący sposób:Jak budować pakiety Pythona bez powtarzania nazwy najwyższego poziomu do importowania?

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

bagoftricks.py zawiera dwie funkcje, levenshtein() i geofind().

chciałbym nazwać je jako:

import bagoftricks 

x = bagoftricks.levenshtein(arg1,arg2) 

Zamiast uważam, muszę to zrobić:

import bagoftricks 

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

Czy istnieje lepszy sposób zorganizować pakietów w pierwszej kolejności, bez nadpisywania nazw?

UPDATE

Więc po instrukcje Avichal Badaya jest poniżej, a usunięty jeden poziom zagnieżdżenia. Oznacza to, że teraz mam ...

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

jednak nazwać tego pakietu, nadal mam ...

from bagoftricks.bagoftricks import geofind() 

lub

import bagoftricks 

następnie

>>> bagoftricks.bagoftricks.geofind() 

Zamiast pożądanego ....

from bagoftricks import geofind() 

lub

import bagoftricks 

>>> bagoftricks.geofind() 

nie mogę usunąć tę dodatkową warstwę gniazdowania. Kiedy próbuję, przez analogię, aby usunąć jeden poziom zagnieżdżenia, tak że mój moduł jest płaska, jak:

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

nie mogę zbudować pakiet w ogóle ...

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

Jaka jest tajne dla importu naturalnego, takiego jak użycie standardowych pakietów, bez nadmiarowego importu nazw najwyższego poziomu?

Odpowiedz

20

Pierwszy poziom "bagoftricks" jest w porządku. To tylko nazwa twojego "projektu", że tak powiem. Masz plik setup.py i inne pliki, które informują systemy pakujące o tym, co muszą wiedzieć.

Możesz następnie wprowadzić kod bezpośrednio w tym module lub w katalogu src. Można nawet iść tak daleko, jak tylko o tę strukturę:

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

Ale nie polecam, że głównie dlatego, że może chcesz zreorganizować rzeczy później, i to jest łatwiejsze, jeśli masz już „właściwej” pakiet. Także większość ludzi, narzędzi i dokumentów przyjmuje, że masz pakiet, więc jest to łatwiejsze.

więc minimalna będzie:

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

Z __init__.py zawierające funkcje, które chcesz importować. Następnie korzystać z tych funkcji tak:

from bagoftricks import levenshtein, anotherfunction 

Raz, że __init__.py staje się zbyt duży, chcesz podzielić ją na kilka modułów, co daje mniej więcej tak:

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

Twój __init__.py powinien wtedy import funkcje z różnych modułów:

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

A potem nadal można z nich korzystać tak jak wcześniej.

+0

Dzięki, to jest jasne i pomocne, szczególnie podpowiedź, jak hodować je skutecznie i prawidłowo. Problemem było zdecydowanie moje zdanie __init__.py. Nie bardzo rozumiałem, gdzie znajduje się w hierarchii i gdzie umieścić to, aby skrócić połączenie. Działa świetnie. Dzięki! – Mittenchops

1

Wykonaj następującą strukturę:

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

a następnie powinny być w stanie użyć go jako:

from bagoftricks.bagoftricks import levenshtein, geofind 

ale po dokonaniu zmian w strukturze folderów zrobić: -

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

i zainstaluj ponownie pakiet

tymczasem sprawdź konfigurację.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(), 
) 

Instalator może mieć również inne parametry. Mam nadzieję, że to zadziała dla ciebie.

+0

IS czy jest jakaś konfiguracja, która pozwoliłaby mi to zrobić jednym połączeniem? Tylko "od bagoftricks importować levenshtein, geofind" zamiast wywołania modułu modemu, "from bagoftricks.bagoftricks import levenshtein, geofind"? – Mittenchops

+0

@Mittenchops put 'from. bagoftricks importować levenshtein, geofind' w twoim 'bagoftricks/__ init __. py' – amigcamel

1

ze zaktualizowanego struktury ty pisał

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 

do innego programu można wykonać follwing

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

pamiętać, że można importować także dziką kartę

from bagoftricks import * 
+0

Mimo że importowanie symboli wieloznacznych takich jak 'from module import *' jest uważane za bardzo złe praktyki, ponieważ może powodować konflikty przestrzeni nazw. Zawsze staraj się importować, nazywając wszystko, co zaimportujesz. – kramer65

+0

tak - masz rację, ale dla tego przykładu jest w porządku - zwróć też uwagę, że moduły z bagoftrick są importowane do workoftricków przestrzeni nazw. – silviud

+0

Po prostu zastanawiam się; dlaczego to jest dobre dla tego przykładu? Jeśli importujesz geofind z bagoftricków, po których importujesz funkcję zwaną także geofind z innego modułu, masz konflikt. Czego tu mi brakuje? Dlaczego ten przykład różni się od innych kodów Pythona? Importowanie za pomocą symboli wieloznacznych to zła praktyka, kropka. – kramer65

Powiązane problemy