Module Python
Modulele sunt fisiere care contin instructiuni si definitii Python (variabile, functii, clase). Rolul modulelor este acela de a imparti programele in unitati care pot fi gestionate mult mai usor.
De exemplu, putem defini un modul care poate contine functii utilizate frecvent, functii ce pot fi astfel incluse in diverse aplicatii in locul copierii codului de definire.
"""Rolul acestui modul este acela de a introduce functii pentru transmiterea de mesaje. | |
Fisier: hello.py | |
Autor: airman | |
Versiune Python: 3.7""" | |
default_name = 'Ghita' | |
def hello_python(): | |
"""Afiseaza un mesaj de tipul Hello Python!""" | |
print('Hello Python!') | |
def hello_name(name = default_name): | |
"""Afiseaza un mesaj personalizat sau Hello Ghita! daca nu se transmite valoare pentru nume""" | |
print('Hello {}!'.format(name)) |
Spatiul de nume de la nivelul unui modul introduce o serie de atribute predefinite, precum __doc__, __file__ sau __name__. Aceste atribute predefinite precizeaza informatii despre modul: descrierea/documentatia, locatia fisierul sursa sau numele modulului.
>>> print(hello.__doc__) Rolul acestui modul este acela de a introduce functii pentru transmiterea de mesaje. Fisier: hello.py Autor: airman Versiune Python: 3.7 >>> print(hello.__file__) C:\Users\airman\virtualcampus\py\hello.py >>> print(hello.__name__) hello
Includere module
Definitiile de la nivelul unui modul Python pot fi incluse intr-un alt modul sau direct in interpretorul Python prin intermediul instructiunii import.
De exemplu pentru a include modulul hello este necesara linia import hello. Numele modulului este astfel introdus la nivelul spatiului de nume curent. Acest nume poate fi utilizat pentru a referi/accesa elemente definite la nivelul modulului.
>>> import hello >>> hello.default_name 'Ghita' >>> hello.hello_name() Hello Ghita! >>> hello.hello_name('Zaya') Hello Zaya! >>> hello.hello_python() Hello Python!
Includerea standard a unui modul permite referirea definitiilor de la nivelul acestuia prin intermediul operatorului ., dupa finalizarea operatiei.
>>> import math >>> math.pi 3.141592653589793
Includerea unui modul se poate realiza si cu redenumirea modulului. Referirea definitiilor de la nivelul modulului se va face, in acest caz, doar prin intermediul noului nume al modulului.
>>> import math as m >>> m.pi 3.141592653589793 >>> math.pi Traceback (most recent call last): File "", line 1, in NameError: name 'math' is not defined
De asemenea, anumite elemente de la nivelul unui modul pot fi incluse explicit prin intermediul clauzei from.
>>> from math import pi >>> pi 3.141592653589793
Chiar daca nu este recomandata includerea tuturor elementelor de la nivelul unui modul, aceasta poate fi realizata folosind *. Astfel, pot fi incluse toate elementele de la nivelul unui modul cu exceptia celor care incep cu underscore. Aceasta abordare poate determina aparitia unor definitii duplicat pentru identificatori.
>>> from math import * >>> pi 3.141592653589793
La includerea unui modul, interpretorul Python are in vedere examinarea urmatoarelor locatii: directorul curent, locatiile definite la nivelul variabilei de mediu PYTHONPATH, directorul implicit de instalare. O modalitatea de actualizarea a locatiilor in care interpretorul Python cauta module o reprezinta sys.path. Noi locatii pot fi adaugate la nivelul acestei structuri de date (list) chiar inaintea rularii unei instructiuni import cu ajutorul metodei append().
>>> import sys >>> sys.path ['', 'C:\\Program Files\\Python37-32\\python37.zip', 'C:\\Program Files\\Python37-32\\DLLs', 'C:\\Program Files\\Python37-32\\lib', 'C:\\Program Files\\Python37-32', 'C:\\Program Files\\Python37-32\\lib\\site-packages'] >>> sys.path.append('C:\\Users\\airman\\virtualcampus\\py')
Interpretorul Python include un modul doar o singura data pe parcursul unei sesiuni. Consideram urmatoarele doua linii la nivelul modulului testare (testare.py).
# modul testare print('Executie cod modul testare')
Codul de la nivelul modulului testare este executat o singura data, daca includerea se face de mai multe ori.
>>> import testare Executie cod modul testare >>> import testare >>> import testare
Daca modulul se modifica in timpul executiei si este necesara reincluderea acestuia, se poate utiliza functia reload() de la nivelul modulului importlib.
>>> import importlib >>> import testare >>> importlib.reload(testare) Executie cod modul testare
Module standard
Python Standard Library contine un numar mare de module utile, ce sunt disponibile la instalarea Python. Lista completa a acestor module standard poate fi consultata in directorul Lib din directorul de instalare. In plus, lista modulelor este disponibila si prin intermediul interpretorului interactiv.
>>> help('modules') Please wait a moment while I gather a list of all available modules... __future__ _tracemalloc glob secrets _abc _warnings gzip select _ast _weakref hashlib selectors _asyncio _weakrefset heapq setuptools _bisect _winapi hmac shelve _blake2 abc html shlex _bootlocale aifc http shutil _bz2 antigravity idlelib signal _codecs argparse imaplib site _codecs_cn array imghdr smtpd _codecs_hk ast imp smtplib _codecs_iso2022 asynchat importlib sndhdr _codecs_jp asyncio inspect socket _codecs_kr asyncore io socketserver _codecs_tw atexit ipaddress sqlite3 _collections audioop itertools sre_compile _collections_abc base64 json sre_constants _compat_pickle bdb keyword sre_parse _compression binascii lib2to3 ssl _contextvars binhex linecache stat _csv bisect locale statistics _ctypes builtins logging string _ctypes_test bz2 lzma stringprep _datetime cProfile macpath struct _decimal calendar mailbox subprocess _dummy_thread cgi mailcap sunau _elementtree cgitb marshal symbol _functools chunk math symtable _hashlib cmath mimetypes sys _heapq cmd mmap sysconfig _imp code modulefinder tabnanny _io codecs msilib tarfile _json codeop msvcrt telnetlib _locale collections multiprocessing tempfile _lsprof colorsys netrc test _lzma compileall nntplib textwrap _markupbase concurrent nt this _md5 configparser ntpath threading _msi contextlib nturl2path time _multibytecodec contextvars numbers timeit _multiprocessing copy opcode tkinter _opcode copyreg operator token _operator crypt optparse tokenize _osx_support csv os trace _overlapped ctypes parser traceback _pickle curses pathlib tracemalloc _py_abc dataclasses pdb tty _pydecimal datetime pickle turtle _pyio dbm pickletools turtledemo _queue decimal pip types _random difflib pipes typing _sha1 dis pkg_resources unicodedata _sha256 distutils pkgutil unittest _sha3 doctest platform urllib _sha512 dummy_threading plistlib uu _signal easy_install poplib uuid _sitebuiltins email posixpath venv _socket encodings pprint warnings _sqlite3 ensurepip profile wave _sre enum pstats weakref _ssl errno pty webbrowser _stat faulthandler py_compile winreg _string filecmp pyclbr winsound _strptime fileinput pydoc wsgiref _struct fnmatch pydoc_data xdrlib _symtable formatter pyexpat xml _testbuffer fractions queue xmlrpc _testcapi ftplib quopri xxsubtype _testconsole functools random zipapp _testimportmultiple gc re zipfile _testmultiphase genericpath reprlib zipimport _thread getopt rlcompleter zlib _threading_local getpass runpy _tkinter gettext sched Enter any module name to get more help. Or, type "modules spam" to search for modules whose name or summary contain the string "spam".
In procesul de explorare a modulelor Python prezinta importanta functiile help() si dir(). Functia help() poate fi utilizata pentru a obtine informatii cu privire la definitiile de la nivelul modulelor.
>>> import math >>> help(math.pow) Help on built-in function pow in module math: pow(x, y, /) Return x**y (x to the power of y).
O functie predefinita foarte puternica de la nivelul Python3 este dir(), functie care poate fi utilizata pentru a obtine numele definitiilor (atribute si metode) ce corespund unui obiect (modul, functie, …).
>>> import math >>> dir(math) ['__doc__', '__loader__', '__name__', '__package__', '__spec__', 'acos', 'acosh', 'asin', 'asinh', 'atan', 'atan2', 'atanh', 'ceil', 'copysign', 'cos', 'cosh', 'degrees', 'e', 'erf', 'erfc', 'exp', 'expm1', 'fabs', 'factorial', 'floor', 'fmod', 'frexp', 'fsum', 'gamma', 'gcd', 'hypot', 'inf', 'isclose', 'isfinite', 'isinf', 'isnan', 'ldexp', 'lgamma', 'log', 'log10', 'log1p', 'log2', 'modf', 'nan', 'pi', 'pow', 'radians', 'remainder', 'sin', 'sinh', 'sqrt', 'tan', 'tanh', 'tau', 'trunc']
Pentru a determina toate numele disponibile in spatiul de nume curent, poate fi utilizata functia dir() fara argumente.
>>> dir() ['__annotations__', '__builtins__', '__doc__', '__loader__', '__name__', '__package__', '__spec__', 'hello', 'm', 'math', 'sys']
Exemplul urmator are in vedere determinarea numelor de la nivelul modulului re care contin un anumit termen (find).
>>> import re >>> [e for e in dir(re) if 'find' in e] ['findall', 'finditer']
Pachete Python
Pachetele reprezinta entitati logice care permit organizarea modulelor de la nivelul unei aplicatii. In limbajul Python, pachetele reprezinta colectii de module similare/inrudite. Aplicatiile pot fi gestionate si intelese mult mai usor prin organizarea lor prin intermediul pachetelor.
Unui pachet ii corespunde un director care poate contine fisiere sursa, subdirectoare, si care contine un tip special de fisier, numit __init__.py. Fisierul __init__.py poate fi gol, sau poate contine cod ce permite initializarea pachetului.
Modulul hello din exemplul precedent poate fi dispus la nivelul unui pachet messages prin crearea unui director cu numele pachetului, director care contine un fisier __init__.py. Tot la nivelul pachetului messages putem introduce un al doilea modul empty, care introduce formule de salut nepersonalizate.
messages/ __init__.py hello.py empty.py
"""Rolul acestui modul este acela de a introduce formule de salut. | |
Fisier: empty.py | |
Autor: airman | |
Versiune Python: 3.7""" | |
def hi(): | |
"""Afiseaza un mesaj de tipul Hi!""" | |
print('Hi!') | |
def ola(): | |
"""Afiseaza un mesaj de tipul Ola!""" | |
print('Ola!') | |
def buna(): | |
"""Afiseaza un mesaj de tipul Buna!""" | |
print('Buna!') |
Daca este necesar, un pachet poate fi organizat ierarhic in subpachete prin alaturarea numelor cu ajutorul operatorului .. Referirea unui modul dintr-un subpachet al unui pachet se face astfel:
pachet.subpachet.modul
Includere pachete
Includerea unui modul de la nivelul unui pachet poate fi realizata prin precizarea in instructiunea import a numelui complet al modulului, nume care precizeaza si pachetul din care acesta faca parte. De exemplu, pentru includerea modulului hello din pachetul messages este necesara urmatoarea instructiune import.
>>> import messages.hello
Referirea functiei hello_python() de la nivelui modulului hello presupune in acest caz utilizarea numelui complet.
>>> messages.hello.hello_python() Hello Python!
Daca se doreste referirea elementelor de la nivelul modulelor unui pachet fara prefixarea cu numele pachetului, includerea trebuie realizata astfel:
>>> from messages import hello, empty >>> hello.hello_name('Casandra') Hello Casandra! >>> empty.hi() Hi!
La includerea unui pachet, interpretorul Python cauta in locatiile stabilite in sys.path pentru a identifica subdirectorul corespunzator acestuia.
>>> import element1.element2.element3
Daca se utilizeaza instructiuni import de genul celei precedente, atunci se considera ca toate elementele cu exceptia ultimului sunt pachete, in timp ce ultimul element este un modul sau un pachet.
>>> from pachet import element
Daca se utilizeaza instructiuni import de genul celei precedente, atunci element este un modul sau un subpachet al pachetului, sau orice alt nume definit la nivelul pachetului (precum o functie, o variabila sau o clasa).
>>> from messages.hello import hello_name >>> help(hello_name) Help on function hello_name in module messages.hello: hello_name(name='Ghita') Afiseaza un mesaj personalizat sau Hello Ghita! daca nu se transmite valoare pentru nume >>> hello_name() Hello Ghita!
Daca la nivelul unui fisier __init__.py, corespunzator unui pachet, se defineste o lista __all__, atunci aceasta va preciza numele de module care vor fi incluse in cazul in care se ruleaza o instructiune de tipul from pachet import *.
__all__ = ['hello', 'empty']
>>> from messages import * >>> hello.hello_name() Hello Ghita! >>> empty.ola() Ola!