# 12. Ambienti Virtuali e Pacchetti

## 12.1. Introduzione

Le applicazioni Python spesso utilizzano pacchetti e moduli che non fanno parte della libreria standard. Le applicazioni a volte necessitano una versione specifica di una libreria, perché l’applicazione potrebbe richiedere che un bug particolare sia stato risolto o l’applicazione potrebbe essere stata scritta utilizzando una versione obsoleta dell’interfaccia della libreria.

Questo significa che potrebbe non essere possibile per una singola installazione di Python soddisfare i requisiti di ogni applicazione. Se l’applicazione A necessita della versione 1.0 di un particolare modulo ma l’applicazione B necessita della versione 2.0, allora i requisiti sono in conflitto e l’installazione della versione 1.0 o 2.0 lascerà una delle applicazioni impossibilitata a funzionare.

La soluzione a questo problema è creare un virtual environment, un albero di directory auto-contenuto che contiene un’installazione di Python per una particolare versione di Python, più un numero di pacchetti aggiuntivi.

Differenti applicazioni possono quindi utilizzare differenti ambienti virtuali. Per risolvere l’esempio precedente di requisiti in conflitto, l’applicazione A può avere il suo proprio ambiente virtuale con la versione 1.0 installata mentre l’applicazione B ha un altro ambiente virtuale con la versione 2.0. Se l’applicazione B richiede che una libreria venga aggiornata alla versione 3.0, questo non influenzerà l’ambiente dell’applicazione A.

## 12.2. Creazione di Ambienti Virtuali

Il modulo utilizzato per creare e gestire ambienti virtuali si chiama `venv`. `venv` installerà la versione di Python dalla quale il comando è stato eseguito (come riportato dall’opzione `--version`). Per esempio, eseguendo il comando con `python3.12` verrà installata la versione 3.12.

Per creare un ambiente virtuale, decidi una directory dove vuoi posizionarlo ed esegui il modulo `venv` come script con il percorso della directory:

    python -m venv tutorial-env

Questo creerà la directory `tutorial-env` se non esiste, e creerà anche directory all’interno contenenti una copia dell’interprete Python e vari file di supporto.

Una posizione comune per una directory di ambiente virtuale è `.venv`. Questo nome mantiene la directory generalmente nascosta nella tua shell e quindi fuori mano, dando anche un nome che spiega il motivo dell’esistenza della directory. Previene anche conflitti con file di definizione di variabili d’ambiente `.env` che alcuni strumenti supportano.

Una volta creato un ambiente virtuale, puoi attivarlo.

Su Windows, esegui:

    tutorial-env\Scripts\activate

Su Unix o MacOS, esegui:

    source tutorial-env/bin/activate

(Questo script è scritto per la shell bash. Se utilizzi le shell csh o fish, ci sono script alternativi `activate.csh` e `activate.fish` che dovresti utilizzare.)

Attivare l’ambiente virtuale cambierà il prompt della tua shell per mostrare quale ambiente virtuale stai utilizzando, e modificherà l’ambiente in modo che eseguire `python` ti fornirà quella versione e installazione particolare di Python. Per esempio:

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

Note that the activated virtual environment does not alter the `PYTHONPATH` variable in any way. This may lead to unexpected results if the path includes references to code which is incompatible with the Python version the virtual environment is using. The best practice is to `unset PYTHONPATH` in bash or the equivalent for the shell you are using.

Per disattivare un ambiente virtuale, scrivi:

    deactivate

nel terminale.

## 12.3. Gestione dei Pacchetti con pip

Puoi installare, aggiornare e rimuovere pacchetti utilizzando un programma chiamato pip. Per impostazione predefinita `pip` installerà pacchetti dal Python Package Index. Puoi sfogliare il Python Package Index andando sul sito web con il tuo browser.

`pip` ha un certo numero di sottocomandi: «install», «uninstall», «freeze», etc. (Consulta la guida Installing Python modules per la documentazione completa su `pip`.)

Puoi installare l’ultima versione di un pacchetto specificando il nome del pacchetto:

    (tutorial-env) $ 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

Puoi anche installare una versione specifica di un pacchetto fornendo il nome del pacchetto seguito da `==` e dal numero di versione:

    (tutorial-env) $ 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

Se esegui nuovamente questo comando, `pip` noterà che la versione richiesta è già installata e non farà nulla. Puoi fornire un numero di versione diverso per ottenere quella versione, oppure puoi eseguire `python -m pip install --upgrade` per aggiornare il pacchetto all’ultima versione:

    (tutorial-env) $ 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` seguito da uno o più nomi di pacchetti rimuoverà i pacchetti dall’ambiente virtuale.

`python -m pip show` mostrerà informazioni su un particolare pacchetto:

    (tutorial-env) $ 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/tutorial-env/lib/python3.4/site-packages
    Requires:

`python -m pip list` mostrerà tutti i pacchetti installati nell’ambiente virtuale:

    (tutorial-env) $ 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` produrrà una lista simile dei pacchetti installati, ma l’output utilizza il formato che `python -m pip install` si aspetta. Una convenzione comune è mettere questa lista in un file `requirements.txt`:

    (tutorial-env) $ python -m pip freeze > requirements.txt
    (tutorial-env) $ cat requirements.txt
    novas==3.1.1.3
    numpy==1.9.2
    requests==2.7.0

Il `requirements.txt` può poi essere committato nel controllo di versione e distribuito come parte di un’applicazione. Gli utenti possono poi installare tutti i pacchetti necessari con `install -r`:

    (tutorial-env) $ python -m pip install -r requirements.txt
    Collecting novas==3.1.1.3 (from -r requirements.txt (line 1))
      ...
    Collecting numpy==1.9.2 (from -r requirements.txt (line 2))
      ...
    Collecting requests==2.7.0 (from -r requirements.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` ha molte altre opzioni. Consulta la guida Installing Python modules per la documentazione completa su `pip`. Quando hai scritto un pacchetto e vuoi renderlo disponibile su Python Package Index, consulta la guida dell’utente al packaging di Python.