https://docs.python.org/3/reference/import.html
PEP 420 - Implicit Namespace Packages [a regular package (with an __init__.py) vs a namespace package]
https://github.com/sympy/sympy
Tworzenie pakietów jest opcją Pythona bardziej zaawansowaną niż tworzenie pojedyńczych modułów. Przy większej liczbie modułów korzystne jest umieszczanie ich w osobnych katalogach, co tworzy kolejne przestrzenie nazw zapobiegające konfliktom nazw.
Python 3 definiuje dwa rodzaje pakietów: pakiety regularne (ang. regular packages) i pakiety przestrzeni nazw (ang. namespace packages).
# Załóżmy, że w katalogu bieżącym mamy moduł główny 'main.py' i moduły: # main.py # dir1/__init__.py (obowiązkowy plik, dir1 to pakiet) # dir1/module1.py # dir1/dir2/__init__.py (obowiązkowy plik, dir2 to podpakiet) # dir1/dir2/module2.py # Instrukcje w module głównym main.py. import dir1.module1 # ścieżka rozdzielona kropką import dir1.dir2.module2
# Postać importu z instrukcją 'from'. from dir1.module1 import name1 from dir1.dir2.module2 import *
Pliki __init__.py mogą zawierać kod Pythona, ale mogą też pozostać puste. Są one obecne jako deklaracje dla Pythona.
Fragment struktury przykładowego pakietu SymPy. Wszystko działa, jeżeli katalog "sympy" znajduje się w zmiennej PYTHONPATH.
sympy/ # główny katalog sympy/__init__.py # obowiązkowy sympy/core/ sympy/core/__init__.py # obowiązkowy sympy/core/basic.py sympy/core/tests/ sympy/core/tests/__init__.py # obowiązkowy sympy/core/tests/test_basic.py # from sympy.core.basic import * # #def test_structure(): # testy dla pytest # assert b21.args == (b2, b1) sympy/combinatorics/ sympy/combinatorics/__init__.py # obowiązkowy sympy/combinatorics/permutations.py # from sympy.core.basic import * sympy/combinatorics/tests/ sympy/combinatorics/tests/__init__.py # obowiązkowy sympy/combinatorics/tests/test_permutations.py # from sympy.combinatorics.permutations import * # from sympy.utilities.pytest import raises sympy/utilities/ sympy/utilities/__init__.py # obowiązkowy
Od Pythona 3.3 pojawiły się pakiety przestrzeni nazw [PEP 420]. Takie pakiety składają się z części (ang. portions), które mogą istnieć w różnych lokalizacjach (katalogach), w sieci, w pliku zip lub nawet mogą nie odpowiadać żadnym obiektom w systemie plików. Dla takich pakietów nie można używać plików __init__.py. Inaczej wygląda konstruowanie sys.path.
PEP 420 zaleca, aby w normalnej sytuacji tworzyć zwykłe pakiety regularne, ponieważ są bardziej wydajne.
https://stackoverflow.com/questions/44977227/how-to-configure-main-py-init-py-and-setup-py-for-a-basic-package
Pojedynczy moduł uruchamiany jako moduł najwyższego poziomu ma ustawiony atrybut __name__ na "__main__". Moduł może dzięki temu sprawdzić jak został uruchomiony.
W przypadku pakietu ten sam efekt można osiągnąć przez dołączenie pliku __main__.py w głównym katalogu modułu [Py3]. Podobnie można uruchamiać archiwum ZIP z kodem pythonowym, jeżeli wewnątrz archiwum jest plik __main__.py.
# Załóżmy, że w katalogu bieżącym mamy moduł główny i moduły: # dir1/__main__.py (jakby punkt wejścia do pakietu) # dir1/__init__.py (obowiązkowy plik dla pakietu) # dir1/module1.py # W wierszu poleceń można uruchomić (nawet bez __init__.py): $ python3 dir1 # przetwarza __main__.py $ python3 -m dir1 # przetwarza __main__.py $ python3 -m dir1.module1 # przetwarza module1