# 10. Breve Panoramica della Libreria Standard

## 10.1. Interfaccia del Sistema Operativo

Il modulo `os` fornisce dozzine di funzioni per interagire con il sistema operativo:

    >>> import os
    >>> os.getcwd()      # Return the current working directory
    'C:\\Python312'
    >>> os.chdir('/server/accesslogs')   # Change current working directory
    >>> os.system('mkdir today')   # Run the command mkdir in the system shell
    0

Assicurati di usare lo stile `import os` invece di `from os import *`. Questo eviterà che `os.open()` sovrasti la funzione built-in `open()` che opera in modo molto diverso.

Le funzioni built-in `dir()` e `help()` sono utili come aiuti interattivi per lavorare con moduli grandi come `os`:

    >>> import os
    >>> dir(os)
    <returns a list of all module functions>
    >>> help(os)
    <returns an extensive manual page created from the module's docstrings>

Per attività quotidiane di gestione di file e directory, il modulo `shutil` fornisce un’interfaccia di livello superiore che è più facile da usare:

    >>> import shutil
    >>> shutil.copyfile('data.db', 'archive.db')
    'archive.db'
    >>> shutil.move('/build/executables', 'installdir')
    'installdir'

## 10.2. Metacaratteri nei Nomfile

Il modulo `glob` fornisce una funzione per creare liste di file a partire da ricerche con metacaratteri nei nomi delle directory:

    >>> import glob
    >>> glob.glob('*.py')
    ['primes.py', 'random.py', 'quote.py']

## 10.3. Argomenti dalla Linea di Comando

Gli script di utilità comuni spesso necessitano di elaborare gli argomenti dalla linea di comando. Questi argomenti sono memorizzati nell’attributo argv del modulo `sys` come una lista. Per esempio, prendiamo il seguente file `demo.py`:

    # File demo.py
    import sys
    print(sys.argv)

Qui c’è l’output eseguendo `python demo.py one two three` dalla linea di comando:

    ['demo.py', 'one', 'two', 'three']

Il modulo `argparse` fornisce un meccanismo più sofisticato per elaborare gli argomenti dalla linea di comando. Il seguente script estrae uno o più nomi di file e un numero opzionale di righe da visualizzare:

    import argparse

    parser = argparse.ArgumentParser(
        prog='top',
        description='Show top lines from each file')
    parser.add_argument('filenames', nargs='+')
    parser.add_argument('-l', '--lines', type=int, default=10)
    args = parser.parse_args()
    print(args)

Quando eseguito dalla linea di comando con `python top.py --lines=5 alpha.txt beta.txt`, lo script assegna `args.lines` a `5` e `args.filenames` a `['alpha.txt', 'beta.txt']`.

## 10.4. Reindirizzamento dell’Uscita degli Errori e Terminazione del Programma

Il modulo `sys` ha anche attributi per stdin, stdout e stderr. Quest’ultimo è utile per emettere avvisi e messaggi di errore per renderli visibili anche quando stdout è stato reindirizzato:

    >>> sys.stderr.write('Warning, log file not found starting a new one\n')
    Warning, log file not found starting a new one

Il modo più diretto per terminare uno script è usare `sys.exit()`.

## 10.5. Pattern Matching di Stringhe

Il modulo `re` fornisce strumenti per le espressioni regolari per l’elaborazione avanzata delle stringhe. Per il matching e la manipolazione complessi, le espressioni regolari offrono soluzioni concise e ottimizzate:

    >>> import re
    >>> re.findall(r'\bf[a-z]*', 'which foot or hand fell fastest')
    ['foot', 'fell', 'fastest']
    >>> re.sub(r'(\b[a-z]+) \1', r'\1', 'cat in the the hat')
    'cat in the hat'

Quando sono necessarie solo semplici capacità, i metodi delle stringhe sono preferiti perché sono più facili da leggere e fare debug:

    >>> 'tea for too'.replace('too', 'two')
    'tea for two'

## 10.6. Matematica

The `math` module gives access to the underlying C library functions for floating-point math:

    >>> import math
    >>> math.cos(math.pi / 4)
    0.70710678118654757
    >>> math.log(1024, 2)
    10.0

Il modulo `random` fornisce strumenti per effettuare selezioni casuali:

    >>> import random
    >>> random.choice(['apple', 'pear', 'banana'])
    'apple'
    >>> random.sample(range(100), 10)   # sampling without replacement
    [30, 83, 16, 4, 8, 81, 41, 50, 18, 33]
    >>> random.random()    # random float
    0.17970987693706186
    >>> random.randrange(6)    # random integer chosen from range(6)
    4

Il modulo `statistics` calcola proprietà statistiche di base (la media, la mediana, la varianza, ecc.) di dati numerici:

    >>> import statistics
    >>> data = [2.75, 1.75, 1.25, 0.25, 0.5, 1.25, 3.5]
    >>> statistics.mean(data)
    1.6071428571428572
    >>> statistics.median(data)
    1.25
    >>> statistics.variance(data)
    1.3720238095238095

Il progetto SciPy <https://scipy.org> ha molti altri moduli per i calcoli numerici.

## 10.7. Accesso a Internet

Ci sono molti moduli per accedere a internet e processare i protocolli internet. Due dei più semplici sono `urllib.request` per recuperare dati da URL e `smtplib` per inviare mail:

    >>> from urllib.request import urlopen
    >>> with urlopen('http://worldtimeapi.org/api/timezone/etc/UTC.txt') as response:
    ...     for line in response:
    ...         line = line.decode()             # Convert bytes to a str
    ...         if line.startswith('datetime'):
    ...             print(line.rstrip())         # Remove trailing newline
    ...
    datetime: 2022-01-01T01:36:47.689215+00:00

    >>> import smtplib
    >>> server = smtplib.SMTP('localhost')
    >>> server.sendmail('soothsayer@example.org', 'jcaesar@example.org',
    ... """To: jcaesar@example.org
    ... From: soothsayer@example.org
    ...
    ... Beware the Ides of March.
    ... """)
    >>> server.quit()

(Nota che il secondo esempio ha bisogno di un mailserver in esecuzione su localhost.)

## 10.8. Date e Orari

Il modulo `datetime` fornisce classi per manipolare date e orari in modi sia semplici che complessi. Mentre l’aritmetica su date e orari è supportata, l’obiettivo dell’implementazione è l’estrazione efficiente dei membri per la formattazione e la manipolazione dell’output. Il modulo supporta anche oggetti che sono consapevoli del fuso orario.

    >>> # dates are easily constructed and formatted
    >>> from datetime import date
    >>> now = date.today()
    >>> now
    datetime.date(2003, 12, 2)
    >>> now.strftime("%m-%d-%y. %d %b %Y is a %A on the %d day of %B.")
    '12-02-03. 02 Dec 2003 is a Tuesday on the 02 day of December.'

    >>> # dates support calendar arithmetic
    >>> birthday = date(1964, 7, 31)
    >>> age = now - birthday
    >>> age.days
    14368

## 10.9. Compressione dei Dati

I formati comuni di archiviazione e compressione dei dati sono direttamente supportati dai moduli inclusi: `zlib`, `gzip`, `bz2`, `lzma`, `zipfile` e `tarfile`.

    >>> import zlib
    >>> s = b'witch which has which witches wrist watch'
    >>> len(s)
    41
    >>> t = zlib.compress(s)
    >>> len(t)
    37
    >>> zlib.decompress(t)
    b'witch which has which witches wrist watch'
    >>> zlib.crc32(s)
    226805979

## 10.10. Misurazione delle Prestazioni

Alcuni utenti di Python sviluppano un profondo interesse nel conoscere le prestazioni relative di diversi approcci allo stesso problema. Python fornisce uno strumento di misurazione che risponde a queste domande immediatamente.

Per esempio, può essere allettante usare la funzione di impacchettamento e spacchettamento delle tuple invece dell’approccio tradizionale per scambiare argomenti. Il modulo `timeit` dimostra rapidamente un modesto vantaggio in termini di prestazioni:

    >>> from timeit import Timer
    >>> Timer('t=a; a=b; b=t', 'a=1; b=2').timeit()
    0.57535828626024577
    >>> Timer('a,b = b,a', 'a=1; b=2').timeit()
    0.54962537085770791

In contrasto con la fine granularità di `timeit`, i moduli `profile` e `pstats` forniscono strumenti per identificare le sezioni critiche in termini di tempo in blocchi di codice più grandi.

## 10.11. Controllo della Qualità

Un approccio per sviluppare software di alta qualità è scrivere test per ogni funzione mentre viene sviluppata e eseguire quei test frequentemente durante il processo di sviluppo.

Il modulo `doctest` fornisce uno strumento per scansionare un modulo e validare i test incorporati nei docstring di un programma. La costruzione dei test è semplice come tagliare e incollare una tipica chiamata con i suoi risultati nel docstring. Questo migliora la documentazione fornendo all’utente un esempio e permette al modulo doctest di assicurarsi che il codice rimanga conforme alla documentazione:

    def average(values):
        """Computes the arithmetic mean of a list of numbers.

        >>> print(average([20, 30, 70]))
        40.0
        """
        return sum(values) / len(values)

    import doctest
    doctest.testmod()   # automatically validate the embedded tests

Il modulo `unittest` non è così semplice come il modulo `doctest`, ma permette di mantenere un insieme più completo di test in un file separato:

    import unittest

    class TestStatisticalFunctions(unittest.TestCase):

        def test_average(self):
            self.assertEqual(average([20, 30, 70]), 40.0)
            self.assertEqual(round(average([1, 5, 7]), 1), 4.3)
            with self.assertRaises(ZeroDivisionError):
                average([])
            with self.assertRaises(TypeError):
                average(20, 30, 70)

    unittest.main()  # Calling from the command line invokes all tests

## 10.12. Batterie Incluse

Python ha una filosofia di «batterie incluse». Questo è reso evidente dalle capacità sofisticate e robuste dei suoi pacchetti più grandi. Per esempio:

- I moduli `xmlrpc.client` e `xmlrpc.server` rendono l’implementazione delle chiamate di procedure remote un compito quasi banale. Nonostante i nomi dei moduli, non è necessaria una conoscenza o una gestione diretta dell’XML.

- Il pacchetto `email` è una libreria per la gestione dei messaggi email, inclusi i messaggi basati su MIME e altri documenti basati su RFC 2822. A differenza di `smtplib` e `poplib` che effettivamente inviano e ricevono messaggi, il pacchetto email ha un set completo di strumenti per costruire o decodificare strutture di messaggi complessi (inclusi allegati) e per implementare protocolli di codifica internet e di intestazioni.

- Il pacchetto `json` fornisce un supporto robusto per il parsing di questo popolare formato di interscambio dati. Il modulo `csv` supporta la lettura e la scrittura diretta di file nel formato Comma-Separated Value, comunemente supportato da database e fogli di calcolo. L’elaborazione XML è supportata dai pacchetti `xml.etree.ElementTree`, `xml.dom` e `xml.sax`. Insieme, questi moduli e pacchetti semplificano notevolmente l’interscambio di dati tra applicazioni Python e altri strumenti.

- Il modulo `sqlite3` è un wrapper per la libreria del database SQLite, fornendo un database persistente che può essere aggiornato e accessibile utilizzando una sintassi SQL leggermente non standard.

- L’internazionalizzazione è supportata da numerosi moduli tra cui `gettext`, `locale` e il pacchetto `codecs`.