# 12. Medii virtuale și pachete

## 12.1. Introducere

Aplicațiile Python folosesc adesea pachete și module care nu fac parte din biblioteca standard. În diverse situații, o aplicație necesită o versiune anumită a unei biblioteci, dat fiind că aplicația în cauză se bazează pe faptul că o defecțiune de cod, din bibliotecă, a fost corectată în versiunea respectivă sau, dimpotrivă, codul aplicației a fost realizat cu elemente dintr-o versiune depășită a interfeței bibliotecii în cauză.

De aceea, se poate întâmpla ca o singură instalare a sistemului Python în calculatorul dumneavoastră să nu poată îndeplini în totalitate cerințele tuturor aplicațiilor pe care intenționați să le folosiți. Dacă, să zicem, aplicația A necesită versiunea 1.0 a modulului cutare pe când aplicația B solicită prezența versiunii 2.0 a respectivului modul, atunci cerințele intră în conflict una cu cealaltă, deci, indiferent pe care dintre versiuni am instala-o, una din aplicațiile A, B nu va putea funcționa.

Soluția unei asemenea probleme este să creăm un mediu virtual, adică un arbore de directoare în care să se găsească o instalare (auto-conținută) completă a sistemului Python corespunzând unei versiuni precizate a Python-ului, instalare căreia să îi fie adăugate un număr de pachete de interes particular.

Astfel, aplicații diferite vor putea fi rulate în medii virtuale diferite. Ca o rezolvare a conflictului de cerințe din exemplul anterior, aplicația A va putea dispune de propriul mediu virtual, în care a fost instalată versiunea 1.0 a modulului respectiv, în timp ce aplicația B va avea la dispoziție alt mediu virtual, cu versiunea 2.0 a aceluiași modul în funcțiune. Presupunând că, în urma unei actualizări, aplicația B va avea nevoie de versiunea 3.0 a unei biblioteci oarecare, instalarea ei nu va afecta în niciun fel mediul aplicației A.

## 12.2. Crearea de medii virtuale

Modulul întrebuințat la crearea și administrarea mediilor virtuale (de execuție, de testare, șamd.) se numește `venv`. Acest `venv` va instala acea versiune de Python pe care o folosim la rularea comenzii de instalare în terminal (și pe care o putem evidenția cu opțiunea `--version`). De exemplu, dacă executăm comanda cu `python3.12`, se va instala versiunea 3.12.

Pentru a crea un mediu virtual, decideți-vă asupra unui director în care să îl plasați, apoi rulați modulul `venv` ca script, furnizându-i calea de acces către directorul convenabil:

    python -m venv tutorialul_de_python_un_mediu_virtual

Execuția comenzii (de către interpretor) va crea directorul `tutorialul_de_python_un_mediu_virtual`, dacă acesta nu există deja, apoi va crea și restul (sub)directoarelor sale, în care se vor găsi o copie a interpretorului de Python și varii fișiere ajutătoare.

O alegere frecventă în privința directorului unui mediu virtual este dată de `.venv`. Un atare nume va face ca directorul să le fie ascuns comenzilor interpretorului de comenzi (de la englezescul, ca jargon informatic, shell) activ în terminalul din care lucrați și, din acest motiv, să nu le fie obstacol acestora, respectiv el nu va avea nevoie de explicații despre motivul pentru care există (atunci când, la câteva luni de la ultima sa folosire, veți fi uitat că face parte din sistemul de directoare). În plus, alegerea acestui nume va elimina potențialele conflicte cu fișierele `.env`, care conțin definițiile unor variabile de mediu, cerute de diverse unelte informatice.

De îndată ce ați creat un mediu virtual, îl puteți activa.

În Windows, rulați:

    tutorialul_de_python_un_mediu_virtual\Scripts\activate

În Unix sau MacOS, rulați:

    source tutorialul_de_python_un_mediu_virtual/bin/activate

(Acest script de activare a fost scris pentru interpretorul de comenzi bash. Dacă îl folosiți ca interpretor fie pe csh fie pe fish, atunci va trebui să utilizați scripturile corespunzătoare, `activate.csh` ori `activate.fish`.)

Activarea mediului virtual va schimba promptul interpretorului de comenzi pe care îl întrebuințați în terminal pentru a vă informa ce mediu virtual este în funcțiune, respectiv va modifica mediul pentru ca rularea comenzii `python` să vă conducă chiar la versiunea (special) instalată de Python cu care doriți să lucrați. De exemplu:

    $ source ~/envs/tutorialul_de_python_un_mediu_virtual/bin/activate
    (tutorialul_de_python_un_mediu_virtual) $ python
    Python 3.5.1 (default, May  6 2016, 10:59:36)
      ...
    >>> import sys
    >>> sys.path
    ['', '/usr/local/lib/python35.zip', ...,
    '~/envs/tutorialul_de_python_un_mediu_virtual/lib/python3.5/site-packages']
    >>>

Pentru a dezactiva un mediu virtual, tastați:

    deactivate

în (linia de comandă din) terminal.

## 12.3. Administrarea pachetelor cu pip

Putem instala, actualiza și elimina pachete cu ajutorul unui program intitulat pip. În mod prestabilit, `pip` instalează pachete preluate din Python Package Index (adică, PyPI; Catalogul pachetelor Python). Pentru a putea răsfoi catalogul, este suficient să îi vizitați pagina web.

`pip` are un număr de sub-comenzi (cu sintaxa pip nume_de_subcomandă): „install”, „uninstall”, „freeze”, șamd. (Consultați ghidul Instalarea modulelor Python pentru o documentație amănunțită referitoare la `pip`.)

Puteți instala cea mai recentă versiune a unui pachet (precum novas) specificându-i numele în comanda:

    (tutorialul_de_python_un_mediu_virtual) $ python -m pip install novas
    Collecting novas
      Downloading novas-3.1.1.3.tar.gz (136kB)
    Installing collected packages: novas
      Running setup.py install for novas
    Successfully installed novas-3.1.1.3

De asemeni, puteți instala o anumită versiune a unui pachet (requests) introducându-i numele (în comandă), urmat de un `==` și de numărul versiunii dorite:

    (tutorialul_de_python_un_mediu_virtual) $ python -m pip install requests==2.6.0
    Collecting requests==2.6.0
      Using cached requests-2.6.0-py2.py3-none-any.whl
    Installing collected packages: requests
    Successfully installed requests-2.6.0

În caz că re-executați comanda, `pip` vă va informa că versiunea solicitată este deja instalată, după care nu va mai face nimic. Desigur, pentru a instala altă versiune (a aceluiași pachet), va fi nevoie să îi introduceți numărul (de versiune) sau veți putea rula comanda `python -m pip install --upgrade` pentru a actualiza pachetul, punându-i în uz cea mai recentă versiune:

    (tutorialul_de_python_un_mediu_virtual) $ python -m pip install --upgrade requests
    Collecting requests
    Installing collected packages: requests
      Found existing installation: requests 2.6.0
        Uninstalling requests-2.6.0:
          Successfully uninstalled requests-2.6.0
    Successfully installed requests-2.7.0

`python -m pip uninstall` urmat de unul ori de mai multe nume de pachete va elimina, în urma execuției, pachetele respective din mediul virtual.

`python -m pip show` va afișa informații despre un pachet precizat:

    (tutorialul_de_python_un_mediu_virtual) $ python -m pip show requests
    ---
    Metadata-Version: 2.0
    Name: requests
    Version: 2.7.0
    Summary: Python HTTP for Humans.
    Home-page: http://python-requests.org
    Author: Kenneth Reitz
    Author-email: me@kennethreitz.com
    License: Apache 2.0
    Location: /Users/akuchling/envs/tutorialul_de_python_un_mediu_virtual/lib/python3.4/site-packages
    Requires:

`python -m pip list` va afișa toate pachetele instalate în mediul virtual:

    (tutorialul_de_python_un_mediu_virtual) $ python -m pip list
    novas (3.1.1.3)
    numpy (1.9.2)
    pip (7.0.3)
    requests (2.7.0)
    setuptools (16.0)

`python -m pip freeze` va produce o listă asemănătoare celei de deasupra, cu excepția faptului că formatul acestei liste este identic celui solicitat de comanda `python -m pip install`. O convenție populară ne spune că lista produsă de freeze trebuie să fie salvată într-un fișier text cu nume sugestiv, precum `cerințe.txt`:

    (tutorialul_de_python_un_mediu_virtual) $ python -m pip freeze > cerințe.txt
    (tutorialul_de_python_un_mediu_virtual) $ cat cerințe.txt
    novas==3.1.1.3
    numpy==1.9.2
    requests==2.7.0

În această situație, fișierul `cerințe.txt` va putea fi comis către (baza de date a platformei de ) controlul versiunii, respectiv livrat (către beneficiari) ca parte a aplicației construite de dumneavoastră. Drept urmare, utilizatorii acesteia vor putea să își instaleze pachetele de care are nevoie aplicația folosind `install -r`:

    (tutorialul_de_python_un_mediu_virtual) $ python -m pip install -r cerințe.txt
    Collecting novas==3.1.1.3 (from -r cerințe.txt (line 1))
      ...
    Collecting numpy==1.9.2 (from -r cerințe.txt (line 2))
      ...
    Collecting requests==2.7.0 (from -r cerințe.txt (line 3))
      ...
    Installing collected packages: novas, numpy, requests
      Running setup.py install for novas
    Successfully installed novas-3.1.1.3 numpy-1.9.2 requests-2.7.0

`pip` are numeroase alte opțiuni. Consultați ghidul Instalarea modulelor Python pentru documentația elaborată a lui `pip`. Dacă ați construit deja un pachet Python și doriți să îl faceți disponibil în catalogul PyPI, vă recomandăm să parcurgeți materialul Python packaging user guide.