Pakiety modułów

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

WPROWADZENIE

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).

PAKIETY REGULARNE


# 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.

STRUKTURA PRZYKŁADOWEGO PAKIETU REGULARNEGO

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

PAKIETY PRZESTRZENI NAZW

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.

TOP-LEVEL SCRIPT ENVIRONMENT

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