Jak utworzyć pakiet przestrzeni nazw w Pythonie?
W Pythonie, pakiet przestrzeni nazw pozwala na rozprzestrzenianie kodu Pythona wśród kilku projektów. Jest to przydatne, gdy chcesz udostępnić powiązane biblioteki jako osobne pliki do pobrania. Na przykład z katalogami Package-1
i Package-2
w PYTHONPATH
,
Package-1/namespace/__init__.py
Package-1/namespace/module1/__init__.py
Package-2/namespace/__init__.py
Package-2/namespace/module2/__init__.py
Użytkownik końcowy może import namespace.module1
i import namespace.module2
.
Jaki jest najlepszy sposób na zdefiniowanie pakietu przestrzeni nazw, aby więcej niż jeden produkt Pythona mógł zdefiniować Moduły w tej przestrzeni nazw?
5 answers
TL; DR:
W Pythonie 3.3 nie musisz nic robić, po prostu nie umieszczaj żadnych __init__.py
w swoich katalogach pakietów przestrzeni nazw, a to po prostu zadziała. W wersji pre-3.3 Wybierz rozwiązanie pkgutil.extend_path()
zamiast pkg_resources.declare_namespace()
, ponieważ jest przyszłościowe i jest już kompatybilne z domyślnymi pakietami przestrzeni nazw.
Python 3.3 wprowadza Ukryte Pakiety przestrzeni nazw, zobacz PEP 420 .
Oznacza to, że obecnie istnieją trzy typy obiektów, które mogą być tworzone przez import foo
:
- moduł reprezentowany przez plik
foo.py
- zwykły pakiet, reprezentowany przez katalog
foo
zawierający plik__init__.py
- pakiet przestrzeni nazw reprezentowany przez jeden lub więcej katalogów
foo
bez żadnych plików__init__.py
Pakiety też są modułami, ale tutaj mam na myśli " non-package module "Kiedy mówię"module".
Najpierw skanuje sys.path
W poszukiwaniu modułu lub zwykłego pakietu. Jeśli się powiedzie, przestaje wyszukiwać i tworzy i initalizuje moduł lub paczka. Jeśli nie znalazł żadnego modułu lub zwykłego pakietu, ale znalazł przynajmniej jeden katalog, tworzy i inicjalizuje pakiet przestrzeni nazw.
Moduły i zwykłe pakiety mają {[12] } ustawiony na .py
Plik, z którego zostały utworzone. Pakiety zwykłe i przestrzenie nazw mają __path__
ustawione na katalog lub katalogi, z których zostały utworzone.
Kiedy wykonasz import foo.bar
, powyższe wyszukiwanie odbywa się najpierw dla foo
, Następnie jeśli pakiet został znaleziony, wyszukiwanie bar
odbywa się z foo.__path__
jako ścieżka wyszukiwania zamiast sys.path
. Jeśli foo.bar
zostanie znaleziony, foo
i foo.bar
zostaną utworzone i zainicjowane.
Więc jak zwykłe pakiety i przestrzenie nazw mieszają się? Zwykle tak nie jest, ale stara metoda jawnego pakietu przestrzeni nazw pkgutil
została rozszerzona o domyślne Pakiety przestrzeni nazw.
Jeśli masz istniejący zwykły pakiet, który ma __init__.py
w ten sposób:
from pkgutil import extend_path
__path__ = extend_path(__path__, __name__)
... zachowanie starsze polega na dodaniu innych zwykłych pakietów na wyszukiwanej ścieżce do its __path__
. Ale w Pythonie 3.3 dodaje również pakiety przestrzeni nazw.
Więc możesz mieć następującą strukturę katalogów:
├── path1
│ └── package
│ ├── __init__.py
│ └── foo.py
├── path2
│ └── package
│ └── bar.py
└── path3
└── package
├── __init__.py
└── baz.py
... i tak długo, jak dwie __init__.py
mają extend_path
linie (i path1
, path2
i path3
są w Twoim sys.path
) import package.foo
, import package.bar
i wszystko będzie działać.
pkg_resources.declare_namespace(__name__)
nie został zaktualizowany, aby zawierał Ukryte Pakiety przestrzeni nazw.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-12-21 02:44:44
Istnieje standardowy moduł o nazwie pkgutil , z którym potrafi "dodawać" moduły do danej przestrzeni nazw.
Z podaną strukturą katalogów:
Package-1/namespace/__init__.py
Package-1/namespace/module1/__init__.py
Package-2/namespace/__init__.py
Package-2/namespace/module2/__init__.py
Należy umieścić te dwie linie w obu Package-1/namespace/__init__.py
i Package-2/namespace/__init__.py
(*):
from pkgutil import extend_path
__path__ = extend_path(__path__, __name__)
(* ponieważ-jeśli nie podasz zależności między nimi - nie wiesz, który z nich zostanie rozpoznany jako pierwszy-zobacz PEP 420 aby uzyskać więcej informacji)
Jak mówi dokumentacja :
To doda do
__path__
pakietu wszystkie podkatalogi katalogów nasys.path
nazwane po pakiecie.
Od teraz powinieneś być w stanie dystrybuować te dwa pakiety niezależnie.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-03-02 23:39:45
Ta sekcja powinna być dość oczywiste.
W skrócie, umieść kod przestrzeni nazw w __init__.py
, zaktualizuj setup.py
, aby zadeklarować przestrzeń nazw, i jesteś wolny.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-01-28 19:47:05
To stare pytanie, ale ktoś ostatnio skomentował na moim blogu, że mój wpis o pakietach przestrzeni nazw jest nadal aktualny, więc pomyślałem, że linkuję do niego tutaj, ponieważ dostarcza praktycznego przykładu, jak to zrobić:
Http://cdent.tumblr.com/post/216241761/python-namespace-packages-for-tiddlyweb
Że linki do tego artykułu dla głównych wnętrzności tego, co się dzieje on:
Http://www.siafoo.net/article/77#multiple-distributions-one-virtual-package
Sztuczka __import__("pkg_resources").declare_namespace(__name__)
jest dość dużo napędza zarządzanie wtyczek w TiddlyWeb i jak dotąd wydaje się działać.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-02-05 15:30:52
Masz swoje koncepcje przestrzeni nazw Pythona z powrotem do przodu, nie jest możliwe w Pythonie umieszczanie pakietów w modułach. Pakiety zawierają moduły nie na odwrót.
Pakiet Pythona jest po prostu folderem zawierającym plik __init__.py
. Moduł to każdy inny plik w pakiecie (lub bezpośrednio w PYTHONPATH
), który ma rozszerzenie .py
. Więc w twoim przykładzie masz dwa pakiety, ale nie zdefiniowano żadnych modułów. Jeśli uważasz, że pakiet jest folderem systemu plików, a moduł jest plikiem, to widzisz dlaczego pakiety zawierają moduły, a nie odwrotnie.
Więc w twoim przykładzie zakładając, że Package-1 i Package-2 są folderami w systemie plików, które umieściłeś na ścieżce Pythona, możesz mieć następujące:
Package-1/
namespace/
__init__.py
module1.py
Package-2/
namespace/
__init__.py
module2.py
Masz teraz jeden pakiet namespace
z dwoma modułami module1
i module2
. i chyba, że masz dobry powód, powinieneś umieścić moduły w folderze i mieć tylko to na ścieżce Pythona, jak poniżej:
Package-1/
namespace/
__init__.py
module1.py
module2.py
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-11-04 18:58:42