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:\\Python313'
>>> 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 from the interval [0.0, 1.0)
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.