6. Module

Dacă, atunci când lucrați în terminal, părăsiți interpretorul Python-ului, veți constata, la revenirea la promptul interpretorului, că toate definițiile scrise în linia de comandă (fie ele definiții de funcții ori de variabile) s-au pierdut. Din acest motiv, atunci când vă pregătiți să scrieți un program mai lung de câteva linii de cod, ar fi mai bine să folosiți un editor de text pentru prepararea acestui program și apoi să rulați programul folosind fișierul în cauză pe post de date de intrare în interpretor. O asemenea întreprindere este numită creare de script. Pe măsură ce programul dumneavoastră se lungește, veți dori să-l împărțiți în mai multe fișiere pentru a-l întreține mai ușor. De asemeni, veți ajunge în situația de a dori să întrebuințați o funcție bine scrisă chiar de dumneavoastră în cadrul unor programe diverse fără să-i copiați, de fiecare dată, codul în vreunul din programele respective.

Pentru a vă ajuta în această privință, Python-ul dispune de o modalitate de a introduce definiții într-un fișier și apoi de a le utiliza fie într-un script fie într-o instanță interactivă a interpretorului. Un astfel de fișier este numit modul; definițiile dintr-un modul pot fi importate atât în alte module cât și în modulul main (modulul principal, adică acea colecție de variabile la care aveți acces dintr-un script executat la nivelul cel mai înalt precum și atunci când lucrați în modul calculator – bucla REPL).

Modulul constituie, așadar, un fișier conținând definiții și instrucțiuni scrise în Python. Numele fișierului este numele modulului la care adăugăm sufixul .py. În interiorul (codului Python al) unui modul, numele modulului (sub forma unui șir de caractere) ne va fi accesibil ca valoare a variabilei globale __name__. Ca să vedem aceasta, vă rugăm să întrebuințați editorul dumneavoastră favorit de text pentru a crea fișierul cu numele fibo.py, situat în directorul curent și având următorul conținut:

# Fibonacci numbers module

def fib(n):    # write Fibonacci series up to n
    a, b = 0, 1
    while a < n:
        print(a, end=' ')
        a, b = b, a+b
    print()

def fib2(n):   # return Fibonacci series up to n
    result = []
    a, b = 0, 1
    while a < n:
        result.append(a)
        a, b = b, a+b
    return result

Apoi, porniți interpretorul de Python și importați modulul tocmai scris cu comanda care urmează:

>>> import fibo

Execuția comenzii nu va adăuga numele funcțiilor definite în fibo direct la spațiul de nume curent (vezi Domenii de valabilitate și spații de nume în Python pentru mai multe detalii); tot ce va face va fi să adauge numele fibo spațiului de nume respectiv. Apelând la numele modulului, veți putea accesa funcțiile acestuia:

>>> fibo.fib(1000)
0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987
>>> fibo.fib2(100)
[0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89]
>>> fibo.__name__
'fibo'

Dacă intenționați să folosiți o anumită funcție în mod frecvent, atunci îi puteți atribui unei variabile locale numele acesteia:

>>> fib = fibo.fib
>>> fib(500)
0 1 1 2 3 5 8 13 21 34 55 89 144 233 377

6.1. Mai multe despre module

Orice modul poate conține atât instrucțiuni executabile cât și definiții de funcții. Aceste instrucțiuni sunt folosite la inițializarea modulului. Adică, ele vor fi executate doar prima dată când numele modulului în cauză va fi întâlnit de către interpretor într-o instrucțiune de import. 1 (Instrucțiunile vor fi rulate și atunci când fișierul – modulul – va fi executat ca script.)

Fiecare modul are propriul său spațiu de nume privat, care va fi utilizat ca spațiu de nume global de către toate funcțiile definite în modulul respectiv. Astfel, autorul unui modul poate întrebuința variabile globale în codul Python al modulului fără să se teamă de eventualele conflicte de nume dintre aceste variabile și variabilele globale ale utilizatorului (modulului). Pe de altă parte, dacă sunteți siguri pe ceea ce faceți, atunci veți putea întrebuința variabilele globale ale unui modul cu aceeași notație pe care o utilizați pentru a vă referi la funcțiile modulului, și anume nume_de_modul.nume_de_item.

Modulele pot importa alte module. Se obișnuiește, fără a fi obligatoriu, să plasăm toate instrucțiunile import la începutul oricărui modul (respectiv, al oricărui script). Numele de module importate, dacă sunt poziționate la nivelul cel mai de sus al modulului (adică, în exteriorul oricărui cod de funcție sau de clasă din modul), vor fi adăugate spațiului de nume global al modulului.

Există o variantă a instrucțiunii import care realizează importurile de nume dintr-un modul direct în spațiul de nume al modulului importator. Iată un exemplu de folosire a ei:

>>> from fibo import fib, fib2
>>> fib(500)
0 1 1 2 3 5 8 13 21 34 55 89 144 233 377

Varianta nu va introduce numele modulului din care facem importurile în spațiul de nume local (așa că, în exemplul anterior, fibo nu este definit).

Dispunem chiar și de o modalitate de a importa toate numele pe care le definește un modul:

>>> from fibo import *
>>> fib(500)
0 1 1 2 3 5 8 13 21 34 55 89 144 233 377

Această variantă a instrucțiunii despre care discutăm va importa toate numele cu excepția celor care încep cu o bară jos (_). De cele mai multe ori, programatorii de Python nu vor apela la această facilitate a limbajului deoarece ea va introduce un set necunoscut de nume în spațiul de nume folosit de interpretor, putând astfel masca o serie de chestiuni deja definite de dumneavoastră.

Să remarcăm, așadar, că obiceiul de a importa * fie dintr-un modul fie dintr-un pachet este descurajat de profesioniști, dat fiind că el cauzează, în majoritatea situațiilor, apariția unui cod greu de citit. Cu toate acestea, este permis să îl practicați în sesiunile interactive de lucru cu interpretorul de Python, ca să aveți mai puțin de tastat.

Dacă numele unui modul este urmat de as, atunci numele situat la dreapta lui as va fi legat direct de modulul importat.

>>> import fibo as fib
>>> fib.fib(500)
0 1 1 2 3 5 8 13 21 34 55 89 144 233 377

Procedând astfel, importul modulului se va realiza la fel ca în urma execuției instrucțiunii import fibo, singura deosebire fiind aceea că modulul va fi disponibil sub numele (modificat convenabil) de fib.

Efecte similare vor fi obținute dacă procedăm în acest mod și atunci când folosim versiunea cu from a instrucțiunii de import:

>>> from fibo import fib as fibonacci
>>> fibonacci(500)
0 1 1 2 3 5 8 13 21 34 55 89 144 233 377

Notă

Din rațiuni de eficiență, orice modul va fi importat o singură dată într-o sesiune de lucru cu interpretorul. Așa că, dacă îi aduceți modificări modulului, va trebui să reporniți interpretorul – ori, dacă este vorba doar despre un singur modul ce trebuie testat interactiv, folosiți importlib.reload(), precum, de exemplu, în import importlib; importlib.reload(numele_modulului).

6.1.1. Executând module ca scripturi

Atunci când rulați un modul Python cu

python fibo.py <arguments>

codul modulului va fi executat ca și cum modulul ar fi fost importat, cu excepția faptului că variabila __name__ va fi setată ca "__main__". Ceea ce înseamnă că, dacă ați adăuga următoarele linii de cod la sfârșitul modulului dumneavoastră:

if __name__ == "__main__":
    import sys
    fib(int(sys.argv[1]))

atunci ați face fișierul (modulului) utilizabil atât ca script cât și ca modul importabil doarece codul în care se parsează conținutul liniei de comandă va rula numai atunci când modulul se execută ca fișier „main”:

$ python fibo.py 50
0 1 1 2 3 5 8 13 21 34

În schimb, atunci când modulul este importat, codul nu va fi rulat:

>>> import fibo
>>>

Acest procedeu este frecvent întrebuințat fie pentru a-i adăuga modulului o interfață cu utilizatorul convenabilă fie în scop de testare (atunci când, la rularea modulului ca script, va fi executată o suită de teste).

6.1.2. Calea de căutare a modulelor

When a module named spam is imported, the interpreter first searches for a built-in module with that name. These module names are listed in sys.builtin_module_names. If not found, it then searches for a file named spam.py in a list of directories given by the variable sys.path. sys.path is initialized from these locations:

  • Directorul care conține scriptul folosit ca dată de intrare la interpretor (sau directorul curent dacă nu a fost precizat niciun fișier).

  • PYTHONPATH (o listă cu nume de directoare, având aceeași sintaxă ca variabila interpretorului de comenzi – de la englezescul shellPATH).

  • Locația implicită, depinzând de modalitatea de instalare (incluzând, în mod convențional, un director site-packages, manipulată de modulul site).

Notă

În sistemele de fișiere care suportă legături slabe (în englezește, ca jargon, symlink), directorul care conține scriptul de intrare va fi calculat numai după ce este urmată legătura. Cu alte cuvinte, directorul care conține legătura slabă nu îi va fi adăugat căii de căutare a modulelor.

Odată inițializate, programele Python pot modifica sys.path-ul. Directorul care conține scriptul ce este rulat va fi plasat la începutul căii de căutare, înaintea căii bibliotecii standard. Ceea ce înseamnă că scripturile din directorul în cauză vor fi încărcate în locul modulelor cu același nume din directorul bibliotecii standard. Dacă aceasta nu este intenția dumneavoastră, atunci situația constituie o eroare serioasă. A se vedea Module standard pentru mai multe informații.

6.1.3. Fișiere Python „compilate”

Pentru a accelera încărcarea modulelor, Python-ul salvează în directorul de cache __pycache__ versiuni compilate ale tuturor modulelor, cu numele modulul.versiunea.pyc, în care versiunea conține codificarea formatului pentru fișierul compilat; în general, ea include numărul de versiune al Python-ului. De exemplu, în ediția (de la englezescul release) 3.3 a CPython-ului, varianta compilată a lui cutare.py ar fi salvată drept __pycache__/cutare.cpython-33.pyc. O atare convenție de nume le permite modulelor compilate ale diverselor ediții și diferitelor versiuni ale Python-ului să coexiste.

Python-ul compară data modificării fișierelor-sursă cu cea a versiunilor compilate pentru a stabili dacă acestea din urmă sunt depășite cronologic și este nevoie să fie recompilate. Procesul de comparare și recompilare este complet automatizat. În plus, modulele compilate sunt independente de platforma de calcul, astfel că aceeași bibliotecă poate fi partajată (de la englezescul shared) cu sisteme de arhitecturi diferite.

Python-ul nu verifică zona de cache în două circumstanțe. În prima, pentru că el recompilează de fiecare dată, fără a stoca rezultatul recompilării în directorul de cache, modulul care se încarcă din linia de comandă. În cea de-a doua situație, el nu verifică zona de cache atunci când modulul nu dispune de fișier-sursă. Pentru ca Python-ul să suporte o distribuție fără cod-sursă (adică una doar compilată), modulul compilat trebuie să fie localizat în directorul-sursă și nu trebuie să existe în distribuție niciun fișier-sursă al modulului în cauză.

Ponturi pentru experți:

  • Puteți întrebuința opțiunile -O sau -OO ale unei comenzi Python pentru a reduce mărimea unui modul compilat. Opțiunea -O elimină instrucțiunile de aserțiune (de la englezescul assert), iar opțiunea -OO elimină atât instrucțiunile de aserțiune cât și șirurile __doc__. Dat fiind că anumite programe se bazează pe existența acestora, ar trebui să utilizați această opțiune numai atunci când sunteți sigur pe ceea ce faceți. Modulele „optimizate” au eticheta opt- și sunt, de obicei, mai mici (decât originalele). Edițiile viitoare ale Python-ului pot modifica efectele acestor optimizări.

  • Niciun program nu va rula mai repede atunci când este citit dintr-un fișier .pyc decât atunci când este citit dintr-un fișier .py; tot ceea ce este mai rapid în privința fișierelor .pyc este viteza cu care sunt încărcate.

  • Modulul compileall le poate crea fișiere .pyc tuturor modulelor dintr-un director.

  • Mult mai multe detalii despre acest proces al compilării modulelor, inclusiv un arbore de decizie util, se găsesc în PEP 3147.

6.2. Module standard

Python-ul vine însoțit de o bibliotecă de module standard, descrisă într-un document separat, Referința bibliotecii Python (denumit „Referința bibliotecii” de aici înainte). Anumite module sunt construite ca parte a interpretorului; ele oferă acces la operații care nu fac parte din corpul (de la englezescul core) limbajului dar sunt, cu toate acestea, incluse în el, fie din rațiuni de eficiență fie pentru a-i da acces utilizatorului la primitive ale sistemului de operare precum apelurile (de) sistem. Setul acestor module este accesibil printr-o opțiune de configurare care depinde, la rândul ei, de platforma de calcul folosită. De exemplu, modulul winreg va fi disponibil numai pe sistemele de calcul cu Windows. Un modul particular merită atenția dumneavoastră: sys, el fiind construit ca parte a oricărui interpretor de Python. Variabilele sys.ps1 și sys.ps2 au drept valori șirurile de caractere folosite pe post de promptul primar, respectiv de promptul secundar:

>>> import sys
>>> sys.ps1
'>>> '
>>> sys.ps2
'... '
>>> sys.ps1 = 'C> '
C> print('Yuck!')
Yuck!
C>

Aceste două variabile sunt definite doar dacă interpretorul lucrează în modul interactiv.

Variabila sys.path este o listă formată din șiruri de caractere care determină calea de căutare a modulelor. Este inițializată cu o cale de acces implicită preluată din variabila de mediu PYTHONPATH, ori dintr-o altă cale de acces prestabilită atunci când PYTHONPATH nu a fost setată. O puteți modifica folosind operațiile tipice cu liste:

>>> import sys
>>> sys.path.append('/ufs/guido/lib/python')

6.3. Funcția dir()

Funcția predefinită dir() este întrebuințată la aflarea numelor pe care le definește un anumit modul. Ea returnează o listă sortată de șiruri de caractere:

>>> import fibo, sys
>>> dir(fibo)
['__name__', 'fib', 'fib2']
>>> dir(sys)  
['__breakpointhook__', '__displayhook__', '__doc__', '__excepthook__',
 '__interactivehook__', '__loader__', '__name__', '__package__', '__spec__',
 '__stderr__', '__stdin__', '__stdout__', '__unraisablehook__',
 '_clear_type_cache', '_current_frames', '_debugmallocstats', '_framework',
 '_getframe', '_git', '_home', '_xoptions', 'abiflags', 'addaudithook',
 'api_version', 'argv', 'audit', 'base_exec_prefix', 'base_prefix',
 'breakpointhook', 'builtin_module_names', 'byteorder', 'call_tracing',
 'callstats', 'copyright', 'displayhook', 'dont_write_bytecode', 'exc_info',
 'excepthook', 'exec_prefix', 'executable', 'exit', 'flags', 'float_info',
 'float_repr_style', 'get_asyncgen_hooks', 'get_coroutine_origin_tracking_depth',
 'getallocatedblocks', 'getdefaultencoding', 'getdlopenflags',
 'getfilesystemencodeerrors', 'getfilesystemencoding', 'getprofile',
 'getrecursionlimit', 'getrefcount', 'getsizeof', 'getswitchinterval',
 'gettrace', 'hash_info', 'hexversion', 'implementation', 'int_info',
 'intern', 'is_finalizing', 'last_traceback', 'last_type', 'last_value',
 'maxsize', 'maxunicode', 'meta_path', 'modules', 'path', 'path_hooks',
 'path_importer_cache', 'platform', 'prefix', 'ps1', 'ps2', 'pycache_prefix',
 'set_asyncgen_hooks', 'set_coroutine_origin_tracking_depth', 'setdlopenflags',
 'setprofile', 'setrecursionlimit', 'setswitchinterval', 'settrace', 'stderr',
 'stdin', 'stdout', 'thread_info', 'unraisablehook', 'version', 'version_info',
 'warnoptions']

Utilizată fără argumente, dir() va lista numele definite în sesiunea curentă:

>>> a = [1, 2, 3, 4, 5]
>>> import fibo
>>> fib = fibo.fib
>>> dir()
['__builtins__', '__name__', 'a', 'fib', 'fibo', 'sys']

Remarcați faptul că ea listează toate tipurile de nume: pe cele de variabile, pe cele de module, de funcții șamd.

dir() nu listează nici numele funcțiilor predefinite (în englezește, ca jargon, built-in) și nici pe cele ale variabilelor predefinite. Dacă vă interesează lista acestora, atunci aflați că ele sunt definite în modulul standard builtins:

>>> import builtins
>>> dir(builtins)  
['ArithmeticError', 'AssertionError', 'AttributeError', 'BaseException',
 'BlockingIOError', 'BrokenPipeError', 'BufferError', 'BytesWarning',
 'ChildProcessError', 'ConnectionAbortedError', 'ConnectionError',
 'ConnectionRefusedError', 'ConnectionResetError', 'DeprecationWarning',
 'EOFError', 'Ellipsis', 'EnvironmentError', 'Exception', 'False',
 'FileExistsError', 'FileNotFoundError', 'FloatingPointError',
 'FutureWarning', 'GeneratorExit', 'IOError', 'ImportError',
 'ImportWarning', 'IndentationError', 'IndexError', 'InterruptedError',
 'IsADirectoryError', 'KeyError', 'KeyboardInterrupt', 'LookupError',
 'MemoryError', 'NameError', 'None', 'NotADirectoryError', 'NotImplemented',
 'NotImplementedError', 'OSError', 'OverflowError',
 'PendingDeprecationWarning', 'PermissionError', 'ProcessLookupError',
 'ReferenceError', 'ResourceWarning', 'RuntimeError', 'RuntimeWarning',
 'StopIteration', 'SyntaxError', 'SyntaxWarning', 'SystemError',
 'SystemExit', 'TabError', 'TimeoutError', 'True', 'TypeError',
 'UnboundLocalError', 'UnicodeDecodeError', 'UnicodeEncodeError',
 'UnicodeError', 'UnicodeTranslateError', 'UnicodeWarning', 'UserWarning',
 'ValueError', 'Warning', 'ZeroDivisionError', '_', '__build_class__',
 '__debug__', '__doc__', '__import__', '__name__', '__package__', 'abs',
 'all', 'any', 'ascii', 'bin', 'bool', 'bytearray', 'bytes', 'callable',
 'chr', 'classmethod', 'compile', 'complex', 'copyright', 'credits',
 'delattr', 'dict', 'dir', 'divmod', 'enumerate', 'eval', 'exec', 'exit',
 'filter', 'float', 'format', 'frozenset', 'getattr', 'globals', 'hasattr',
 'hash', 'help', 'hex', 'id', 'input', 'int', 'isinstance', 'issubclass',
 'iter', 'len', 'license', 'list', 'locals', 'map', 'max', 'memoryview',
 'min', 'next', 'object', 'oct', 'open', 'ord', 'pow', 'print', 'property',
 'quit', 'range', 'repr', 'reversed', 'round', 'set', 'setattr', 'slice',
 'sorted', 'staticmethod', 'str', 'sum', 'super', 'tuple', 'type', 'vars',
 'zip']

6.4. Pachete

Packages are a way of structuring Python’s module namespace by using „dotted module names”. For example, the module name A.B designates a submodule named B in a package named A. Just like the use of modules saves the authors of different modules from having to worry about each other’s global variable names, the use of dotted module names saves the authors of multi-module packages like NumPy or Pillow from having to worry about each other’s module names.

Să presupunem că doriți să proiectați o colecție de module (adică, un „pachet”) dedicate manipulării sistematice a fișierelor de sunet și a datelor audio. Deoarece există numeroase formate de fișier de sunet (recunoscute, de obicei, după extensiile lor, cum ar fi: .wav, .aiff, .au), veți avea de construit și de întreținut o colecție crescândă de module care să se ocupe cu conversia între diversele formate de fișier. De asemeni, există felurite operații pe care veți dori să le aplicați unor date audio (precum mixaje, adăugarea de ecouri, aplicarea unor funcții de egalizare, crearea unor efecte stereo artificiale), astfel că, pe lângă cele de dinainte, veți scrie în permanență noi module pentru aceste operații. Iată o structură posibilă a pachetului dumneavoastră (exprimată în stilul unui sistem ierarhic de fișiere – în englezește, ca jargon, filesystem):

sound/                          Top-level package
      __init__.py               Initialize the sound package
      formats/                  Subpackage for file format conversions
              __init__.py
              wavread.py
              wavwrite.py
              aiffread.py
              aiffwrite.py
              auread.py
              auwrite.py
              ...
      effects/                  Subpackage for sound effects
              __init__.py
              echo.py
              surround.py
              reverse.py
              ...
      filters/                  Subpackage for filters
              __init__.py
              equalizer.py
              vocoder.py
              karaoke.py
              ...

Atunci când importăm un pachet, Python-ul va căuta subdirectorul pachetului în lista de directoare din sys.path.

The __init__.py files are required to make Python treat directories containing the file as packages. This prevents directories with a common name, such as string, from unintentionally hiding valid modules that occur later on the module search path. In the simplest case, __init__.py can just be an empty file, but it can also execute initialization code for the package or set the __all__ variable, described later.

Utilizatorii unui pachet pot importa module individuale din acesta, ca de exemplu:

import sound.effects.echo

This loads the submodule sound.effects.echo. It must be referenced with its full name.

sound.effects.echo.echofilter(input, output, delay=0.7, atten=4)

Alt fel de a importa submodulul anterior este dat de:

from sound.effects import echo

This also loads the submodule echo, and makes it available without its package prefix, so it can be used as follows:

echo.echofilter(input, output, delay=0.7, atten=4)

Încă o variație a modului de a importa este să importăm direct fie funcția fie variabila dorită:

from sound.effects.echo import echofilter

Again, this loads the submodule echo, but this makes its function echofilter() directly available:

echofilter(input, output, delay=0.7, atten=4)

Să remarcăm că, atunci când executăm instrucțiunea from pachet import element, elementul poate fi sau un submodul (ori un subpachet) al pachetului sau orice alt nume definit în pachet, adică o funcție, o clasă ori o variabilă. Instrucțiunea import testează mai întâi dacă elementul este definit în pachet; dacă nu, atunci va presupune că elementul este numele unui modul și va încerca să-l încarce. În cazul în care presupusul modul nu va fi găsit, va fi ridicată o excepție ImportError.

În schimb, atunci când facem uz de o sintaxă de felul import element.sub_element.sub_sub_element, fiecare (sub)element, cu excepția ultimului, trebuie să fie nume de pachet; ultimul element poate fi sau nume de modul sau nume de pachet însă nu și numele vreunei clase, funcții ori variabile definite în elementul precedent.

6.4.1. Importând * dintr-un pachet

Ce se întâmplă însă atunci când utilizatorul folosește instrucțiunea from sunet.efecte import *? În mod ideal, putem spera că interpretorul se duce la sistemul de fișiere, găsește toate (sub)modulele prezente în pachet și le importă. O atare activitate este de așteptat să dureze mult iar importul de sub-module poate avea și efecte secundare nedorite pe care nu le-am produce dacă importul unui sub-modul oarecare ar fi realizat în mod explicit.

Singurul mod în care putem evita situațiile neplăcute este ca autorul pachetului să ofere un index explicit al acestuia. Instrucțiunea import folosește următoarea convenție: atunci când codul-sursă al fișierului __init__.py dintr-un pachet definește o variabilă de tip listă numită __all__, valoarea acestei variabile va fi folosită drept lista numelor de module ce vor trebui importate atunci când interpretorul va avea de executat instrucțiunea from pachet import *. Actualizarea listei de nume, cu ocazia lansării unei noi versiuni a pachetului, rămâne numai la latitudinea autorului acestuia. Autorii de pachete pot decide chiar și să nu întrebuințeze această facilitate atunci când nu consideră că ar fi de vreun folos să se importe * din pachetele lor. Ca exemplu, să presupunem că fișierul sunet/efecte/__init__.py ar conține următoarea linie de cod:

__all__ = ["echo", "surround", "reverse"]

This would mean that from sound.effects import * would import the three named submodules of the sound.effects package.

If __all__ is not defined, the statement from sound.effects import * does not import all submodules from the package sound.effects into the current namespace; it only ensures that the package sound.effects has been imported (possibly running any initialization code in __init__.py) and then imports whatever names are defined in the package. This includes any names defined (and submodules explicitly loaded) by __init__.py. It also includes any submodules of the package that were explicitly loaded by previous import statements. Consider this code:

import sound.effects.echo
import sound.effects.surround
from sound.effects import *

In this example, the echo and surround modules are imported in the current namespace because they are defined in the sound.effects package when the from...import statement is executed. (This also works when __all__ is defined.)

Cu toate că anumite module au fost proiectate să nu exporte decât acele nume care respectă șabloane precise atunci când dumneavoastră veți folosi instrucțiunea import * în raport de ele, întrebuințarea acestei instrucțiuni în codul destinat producției se socotește a fi o practică greșită.

Țineți minte, nu este nimic în neregulă dacă utilizați instrucțiunea from pachet import submodulul_cutare! De fapt, aceasta constituie chiar formularea recomandată a oricărei instrucțiuni de import, cu excepția situației în care modulul importator are de folosit submodule omonime din pachete diferite.

6.4.2. Referințe intra-pachet

When packages are structured into subpackages (as with the sound package in the example), you can use absolute imports to refer to submodules of siblings packages. For example, if the module sound.filters.vocoder needs to use the echo module in the sound.effects package, it can use from sound.effects import echo.

You can also write relative imports, with the from module import name form of import statement. These imports use leading dots to indicate the current and parent packages involved in the relative import. From the surround module for example, you might use:

from . import echo
from .. import formats
from ..filters import equalizer

Note that relative imports are based on the name of the current module. Since the name of the main module is always "__main__", modules intended for use as the main module of a Python application must always use absolute imports.

6.4.3. Pachete situate în mai multe directoare

Packages support one more special attribute, __path__. This is initialized to be a list containing the name of the directory holding the package’s __init__.py before the code in that file is executed. This variable can be modified; doing so affects future searches for modules and subpackages contained in the package.

Deși este o caracteristică de care avem nevoie rar, o putem folosi cu succes la lărgirea setului de module conținute într-un pachet.

Note de subsol

1

De fapt, și definițiile de funcții sunt «instrucțiuni» care se «execută»; execuția unei definiții de funcție de la nivel de modul va adăuga numele acestei funcții la spațiul de nume global al modulului respectiv.