Na init.py nie jest wymagane dla pakietów w Pythonie 3.3+
Używam Pythona 3.5.1. Przeczytałem dokument i sekcję pakiet tutaj: https://docs.python.org/3/tutorial/modules.html#packages
Teraz mam następującą strukturę:
/home/wujek/Playground/a/b/module.py
module.py
:
class Foo:
def __init__(self):
print('initializing Foo')
Teraz, gdy w /home/wujek/Playground
:
~/Playground $ python3
>>> import a.b.module
>>> a.b.module.Foo()
initializing Foo
<a.b.module.Foo object at 0x100a8f0b8>
Podobnie, teraz w domu, superfolder z Playground
:
~ $ PYTHONPATH=Playground python3
>>> import a.b.module
>>> a.b.module.Foo()
initializing Foo
<a.b.module.Foo object at 0x10a5fee10>
Właściwie, mogę robić różne rzeczy:
~ $ PYTHONPATH=Playground python3
>>> import a
>>> import a.b
>>> import Playground.a.b
Dlaczego to działa? I thought there need to be __init__.py
files (puste będą działać) zarówno w a
jak i b
dla module.py
, aby można było importować, gdy ścieżka Pythona wskazuje na folder Playground
?
Wydaje się, że to się zmieniło od Pythona 2.7:
~ $ PYTHONPATH=Playground python
>>> import a
ImportError: No module named a
>>> import a.b
ImportError: No module named a.b
>>> import a.b.module
ImportError: No module named a.b.module
Z __init__.py
w obu ~/Playground/a
i ~/Playground/a/b
działa dobrze.
5 answers
Python 3.3 + posiada domyślne Pakiety przestrzeni nazw , które umożliwiają tworzenie pakietów bez pliku __init__.py
.
Umożliwienie domyślnej przestrzeni nazw pakietów oznacza, że wymóg dostarczenia pliku
__init__.py
może zostać całkowicie usunięty, i może zostać naruszony ... .
Stary sposób z plikami __init__.py
nadal działa jak w Pythonie 2.
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
2018-12-13 01:46:16
Przegląd
@ Mike odpowiedź jest poprawna, ale zbyt nieprecyzyjna . To prawda, że Python 3.3 + obsługuje Ukryte Pakiety przestrzeni nazw , które pozwalają na utworzenie pakietu bez pliku __init__.py
. Jest to pakiet przestrzeni nazw W przeciwieństwie do zwykłego pakietu, który ma Plik __init__.py
(pusty lub nie pusty).
Jednak tworzenie pakietu przestrzeni nazw powinno być wykonywane tylko wtedy, gdy istnieje taka potrzeba. Dla większości przypadków użycia i deweloperzy tam, to nie ma zastosowania, więc należy trzymać się puste __init__.py
/ align = "left" /
Przypadek użycia pakietu przestrzeni nazw
Aby zademonstrować różnicę między dwoma typami pakietów Pythona, spójrzmy na poniższy przykład:
google_pubsub/ <- Package 1
google/ <- Namespace package (there is no __init__.py)
cloud/ <- Namespace package (there is no __init__.py)
pubsub/ <- Regular package (with __init__.py)
__init__.py <- STILL REQUIRED to make the package a regular package and to run some initialization
foo.py
google_storage/ <- Package 2
google/ <- Namespace package (there is no __init__.py)
cloud/ <- Namespace package (there is no __init__.py)
storage/ <- Regular package (with __init__.py)
__init__.py <- STILL REQUIRED to make the package a regular package and to run some initialization
bar.py
google_pubsub
i google_storage
są oddzielnymi pakietami, ale mają tę samą przestrzeń nazw google/cloud
. Aby współdzielić tę samą przestrzeń nazw, wymagane jest, aby każdy katalog wspólnej ścieżki był pakietem przestrzeni nazw, tzn. google/
i cloud/
. to powinien być jedyny przypadek użycia do tworzenia pakietów przestrzeni nazw, w przeciwnym razie nie ma takiej potrzeby.
Ważne jest, aby w katalogach google
i google/cloud
nie było plików __init__py
, aby oba katalogi mogły być interpretowane jako pakiety przestrzeni nazw . W Pythonie 3.3 + każdy katalog sys.path
z nazwą odpowiadającą wyszukiwanej nazwie pakietu będzie rozpoznawany jako moduły i podpakiety do tego pakietu. W rezultacie, podczas importu zarówno z google_pubsub
, jak i google_storage
, interpreter Pythona będzie w stanie je znaleźć.
Różni się to od zwykłych pakietów , które są samodzielne, co oznacza, że wszystkie części żyją w tej samej hierarchii katalogów. Gdy importowanie pakietu i interpreter Pythona napotka podkatalog sys.path
z plikiem __init__.py
, wtedy utworzy pojedynczy katalog zawierający tylko moduły z tego katalogu, zamiast znajdować wszystkie odpowiednio nazwane podkatalogi poza tym katalog. jest to idealne rozwiązanie dla pakietów, które nie chcą współdzielić przestrzeni nazw . Bardzo polecam zajrzeć do pułapek dla Unwary w systemie importowania Pythona, aby lepiej zrozumieć, jak zaimportowanie Pythona zachowuje się z pakietem regularnym i przestrzenią nazw oraz na jakie pułapki __init__.py
Należy uważać.
Podsumowanie
- pomiń tylko pliki
__init__.py
, jeśli chcesz utworzyć Pakiety przestrzeni nazw. Twórz tylko pakiety przestrzeni nazw, jeśli masz inne pakiety biblioteki, które znajdują się w różnych lokalizacjach i chcesz, aby każda z nich dodała podpakiet do pakietu nadrzędnego, tj. pakietu przestrzeni nazw. - dodawaj puste
__init__py
do swoich katalogów, ponieważ w 99% przypadków chcesz tylko tworzyć zwykłe Pakiety. Ponadto, narzędzia Pythona, takie jakmypy
ipytest
wymagają pustych plików__init__.py
, aby odpowiednio zinterpretować strukturę kodu. Ponownie, może to prowadzić do dziwnych błędów, jeśli nie zostanie zrobione z care.
Zasoby
Moja odpowiedź dotyka tylko tego, jak działają zwykłe Pakiety i Pakiety przestrzeni nazw, więc zajrzyj do następujących zasobów, aby uzyskać więcej informacji:
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
2021-02-14 10:40:46
Jeśli masz setup.py
w swoim projekcie i używasz find_packages()
w jego obrębie, konieczne jest posiadanie pliku __init__.py
w każdym katalogu, aby Pakiety mogły zostać automatycznie znalezione.
Pakiety są rozpoznawane tylko wtedy, gdy zawierają plik
__init__.py
UPD: Jeśli chcesz użyć domyślnych pakietów przestrzeni nazw Bez __init__.py
, musisz użyć find_namespace_packages()
zamiast
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
2020-04-12 15:26:37
Powiedziałbym, że należy pominąć __init__.py
tylko wtedy, gdy chcemy mieć ukryty pakiet przestrzeni nazw . Jeśli nie wiesz, co to znaczy, prawdopodobnie nie chcesz go używać i dlatego powinieneś nadal używać __init__.py
nawet w Pythonie 3.
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
2019-03-05 08:29:54
Bazując na moim doświadczeniu, nawet z Pythonem 3.3+, pusty __init__.py
jest nadal czasami potrzebny. Jedną z sytuacji jest to, gdy chcesz odnieść podfolder do pakietu. Na przykład, gdy uruchomiłem python -m test.foo
, nie zadziałało, dopóki nie utworzyłem pustego __init__.py
w folderze testowym. A ja mówię tu o wersji 3.6.6, która jest całkiem niedawno.
Poza tym, nawet ze względu na kompatybilność z istniejącym kodem źródłowym lub wytycznymi projektu, miło jest mieć puste __init__.py
w folderze pakietu.
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
2020-11-28 04:08:58