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".
