Python & AI Tutorials Logo
Programmazione Python

29. Interagire con il sistema operativo: sys e os

I programmi Python non esistono in isolamento: vengono eseguiti su un sistema operativo che gestisce file, directory, impostazioni dell’ambiente e il modo in cui i programmi si avviano e comunicano. I moduli sys e os forniscono strumenti per interagire con questo ambiente, permettendo ai tuoi programmi di accettare argomenti da riga di comando, leggere variabili d’ambiente, navigare nel file system e creare o rimuovere directory.

Comprendere questi moduli trasforma i tuoi script Python da codice isolato a programmi in grado di integrarsi con il sistema più ampio, rispondere all’input dell’utente all’avvio e gestire file e cartelle in modo programmatico.

29.1) Argomenti da riga di comando e uso di sys.argv

Quando esegui uno script Python dal terminale o dal prompt dei comandi, puoi passargli informazioni aggiuntive: si chiamano argomenti da riga di comando. Per esempio:

bash
python greet.py Alice 25

Qui greet.py è il nome dello script, e Alice e 25 sono argomenti passati al programma. Il modulo sys fornisce accesso a questi argomenti tramite sys.argv, una lista(list) che contiene il nome dello script e tutti gli argomenti come stringhe.

29.1.1) Che cos’è sys.argv?

sys.argv è una lista(list) in cui:

  • sys.argv[0] è sempre il nome dello script in esecuzione
  • sys.argv[1], sys.argv[2], ecc. sono gli argomenti passati dopo il nome dello script
  • Tutti gli elementi sono stringhe, anche se sembrano numeri

Creiamo uno script semplice per vedere come funziona:

python
# show_args.py
import sys
 
print("Script name:", sys.argv[0])
print("Number of arguments:", len(sys.argv))
print("All arguments:", sys.argv)

Se esegui questo script con:

bash
python show_args.py hello world 123

Output:

Script name: show_args.py
Number of arguments: 4
All arguments: ['show_args.py', 'hello', 'world', '123']

Nota che sys.argv contiene 4 elementi: il nome dello script più tre argomenti. Il numero 123 è memorizzato come stringa '123', non come intero.

29.1.2) Usare gli argomenti da riga di comando nei programmi

Gli argomenti da riga di comando permettono agli utenti di personalizzare il comportamento del programma senza modificare il codice. Ecco un programma di saluto che usa il primo argomento come nome:

python
# greet.py
import sys
 
if len(sys.argv) < 2:
    print("Usage: python greet.py <name>")
    sys.exit(1)  # Esce con un codice di errore
 
name = sys.argv[1]
print(f"Hello, {name}!")

Eseguendolo:

bash
python greet.py Alice

Output:

Hello, Alice!

Se dimentichi di fornire un nome:

bash
python greet.py

Output:

Usage: python greet.py <name>

Il programma controlla se sono stati forniti abbastanza argomenti. In caso contrario, stampa un messaggio d’uso ed esce con sys.exit(1). Il numero 1 è un codice di uscita: per convenzione, 0 significa successo e valori diversi da zero indicano errori. Questo aiuta altri programmi o script a rilevare se il tuo programma è stato eseguito correttamente.

29.1.3) Convertire gli argomenti in altri tipi

Poiché tutti gli argomenti arrivano come stringhe, spesso devi convertirli. Ecco un programma che calcola l’area di un rettangolo:

python
# area.py
import sys
 
if len(sys.argv) < 3:
    print("Usage: python area.py <width> <height>")
    sys.exit(1)
 
try:
    width = float(sys.argv[1])
    height = float(sys.argv[2])
except ValueError:
    print("Error: Width and height must be numbers")
    sys.exit(1)
 
area = width * height
print(f"Area: {area}")

Eseguendolo:

bash
python area.py 5.5 3.2

Output:

Area: 17.6

Se l’utente fornisce un input non valido:

bash
python area.py five three

Output:

Error: Width and height must be numbers

Il blocco try-except (dal Capitolo 25) gestisce in modo elegante gli errori di conversione, fornendo un feedback utile invece di andare in crash con un traceback.

L’utente esegue: python script.py arg1 arg2

Python crea la lista sys.argv

sys.argv[0] = 'script.py'

sys.argv[1] = 'arg1'

sys.argv[2] = 'arg2'

Lo script accede a sys.argv

Elabora gli argomenti come stringhe

Converte i tipi se necessario

Usa i valori nella logica del programma

29.2) Ottenere informazioni sull’interprete e sul runtime con sys

Il modulo sys fornisce informazioni sull’interprete Python stesso e sull’ambiente di runtime. Questo è utile per il debugging, il logging o per scrivere codice che si adatta a diverse versioni di Python o piattaforme.

29.2.1) Informazioni sulla versione di Python

sys.version e sys.version_info ti dicono quale versione di Python sta eseguendo il tuo codice:

python
import sys
 
print("Python version string:", sys.version)
print("Version info:", sys.version_info)
print(f"Major version: {sys.version_info.major}")
print(f"Minor version: {sys.version_info.minor}")

Output (esempio):

Python version string: 3.11.4 (main, Jul  5 2023, 13:45:01) [GCC 11.2.0]
Version info: sys.version_info(major=3, minor=11, micro=4, releaselevel='final', serial=0)
Major version: 3
Minor version: 11

sys.version è una stringa leggibile dall’uomo, mentre sys.version_info è una named tuple che puoi confrontare a livello programmatico:

python
import sys
 
if sys.version_info < (3, 8):
    print("This program requires Python 3.8 or higher")
    sys.exit(1)
 
print("Python version is compatible")

Questo assicura che il tuo programma venga eseguito solo su versioni di Python supportate.

29.2.2) Informazioni sulla piattaforma

sys.platform identifica il sistema operativo:

python
import sys
 
print("Platform:", sys.platform)
 
if sys.platform == "win32":
    print("Running on Windows")
elif sys.platform == "darwin":
    print("Running on macOS")
elif sys.platform.startswith("linux"):
    print("Running on Linux")
else:
    print("Running on another platform")

Output (su Linux):

Platform: linux
Running on Linux

Questo ti permette di scrivere codice specifico per piattaforma quando necessario, ad esempio usando percorsi di file diversi o comandi di sistema differenti.

29.2.3) Percorso di ricerca dei moduli

sys.path è una lista(list) di directory in cui Python cerca quando importi moduli:

python
import sys
 
print("Module search paths:")
for path in sys.path:
    print(f"  {path}")

Output (esempio):

Module search paths:
  /home/user/projects
  /usr/lib/python3.11
  /usr/lib/python3.11/lib-dynload
  /home/user/.local/lib/python3.11/site-packages

La prima voce è di solito la directory che contiene il tuo script. Python cerca in questi percorsi in ordine quando usi import. Comprendere sys.path aiuta a fare debugging degli errori di import o ad aggiungere directory di moduli personalizzate.

29.2.4) Uscire dai programmi con codici di uscita

Abbiamo visto sys.exit() usato per fermare i programmi. Puoi passare un codice di uscita per indicare successo o fallimento:

python
import sys
 
def process_data(filename):
    try:
        with open(filename) as f:
            data = f.read()
        # Elabora i dati...
        return True
    except FileNotFoundError:
        print(f"Error: File '{filename}' not found", file=sys.stderr)
        return False
 
if __name__ == "__main__":
    if len(sys.argv) < 2:
        print("Usage: python script.py <filename>", file=sys.stderr)
        sys.exit(1)
    
    success = process_data(sys.argv[1])
    sys.exit(0 if success else 1)

I codici di uscita seguono le convenzioni Unix:

  • 0 significa successo
  • Valori diversi da zero indicano diversi tipi di errori
  • Altri programmi possono controllare questi codici per determinare se il tuo programma ha avuto successo

29.3) Accedere alle variabili d’ambiente con os

Le variabili d’ambiente sono coppie chiave-valore impostate dal sistema operativo o dall’utente che i programmi possono leggere. Sono usate per la configurazione, per memorizzare percorsi, chiavi API e altre impostazioni che non dovrebbero essere hardcoded.

29.3.1) Leggere le variabili d’ambiente

Il modulo os fornisce os.environ, un oggetto simile a un dizionario che contiene tutte le variabili d’ambiente:

python
import os
 
# Ottiene una specifica variabile d’ambiente
home = os.environ.get('HOME')  # On Unix/Linux/macOS
print(f"Home directory: {home}")
 
# Restituisce None se la variabile non esiste
api_key = os.environ.get('MY_API_KEY')
print(f"API key: {api_key}")

Output (su Linux):

Home directory: /home/alice
API key: None

Puoi fornire un valore predefinito:

python
import os
 
# Ottiene una variabile d’ambiente con valore predefinito
log_level = os.environ.get('LOG_LEVEL', 'INFO')
print(f"Log level: {log_level}")

Output (se LOG_LEVEL non è impostata):

Log level: INFO

29.3.2) Variabili d’ambiente comuni

Sistemi operativi diversi forniscono variabili d’ambiente standard:

python
import os
 
# Variabili cross-platform
print("Path:", os.environ.get('PATH'))
 
# Unix/Linux/macOS
print("User:", os.environ.get('USER'))
print("Home:", os.environ.get('HOME'))
print("Shell:", os.environ.get('SHELL'))
 
# Windows
print("User", os.environ.get('USERNAME'))
print("User Profile:", os.environ.get('USERPROFILE'))
print("Temp:", os.environ.get('TEMP'))

PATH è particolarmente importante: elenca le directory in cui il sistema cerca i programmi eseguibili. Quando digiti un comando come python, il sistema cerca in queste directory.

29.3.3) Impostare variabili d’ambiente

Puoi modificare le variabili d’ambiente per il tuo programma e per eventuali sottoprocessi che crea:

python
import os
 
# Imposta una variabile d’ambiente
os.environ['MY_CONFIG'] = 'production'
 
# La rilegge
print(os.environ.get('MY_CONFIG'))  # Output: production
 
# Elimina una variabile d’ambiente
del os.environ['MY_CONFIG']

Importante: le modifiche a os.environ influenzano solo l’attuale processo Python e qualsiasi programma che esso avvia. Non persistono dopo l’uscita del programma né influenzano altri programmi.

29.4) Lavorare con percorsi di file e directory (os.path, os.getcwd)

Gestire correttamente i percorsi dei file è cruciale per i programmi che lavorano con i file. I moduli os e os.path forniscono strumenti per costruire, manipolare e interrogare percorsi in modo indipendente dalla piattaforma.

29.4.1) Ottenere la directory di lavoro corrente

La directory di lavoro corrente (CWD) è la cartella che il programma considera come punto di partenza per i percorsi relativi:

python
import os
 
cwd = os.getcwd()
print(f"Current working directory: {cwd}")

Output (esempio):

Current working directory: /home/alice/projects/myapp

Quando apri un file con un percorso relativo come 'data.txt', Python lo cerca nella directory di lavoro corrente. Comprendere la CWD aiuta a fare debugging degli errori “file not found”.

29.4.2) Cambiare la directory corrente

Puoi cambiare la directory di lavoro con os.chdir():

python
import os
 
original = os.getcwd()
print("Original directory:", original)
 
# Cambia in una directory diversa
os.chdir('/tmp')
print("New directory:", os.getcwd())
 
# Torna indietro
os.chdir(original)
print("Back to:", os.getcwd())

Output:

Original directory: /home/alice/projects
New directory: /tmp
Back to: /home/alice/projects

Nota: Nel Capitolo 28 hai imparato contextlib.chdir(), che ripristina automaticamente la directory originale. Per cambi di directory semplici, preferisci usare il context manager:

python
from contextlib import chdir
 
with chdir('/tmp'):
    print("Temporarily in:", os.getcwd())
# Automatically restored

Questo assicura che la directory venga sempre ripristinata, anche se si verifica un errore.

29.4.3) Costruire percorsi con os.path.join()

Sistemi operativi diversi usano separatori di percorso diversi:

  • Unix/Linux/macOS: / (barra)
  • Windows: \ (backslash)

os.path.join() costruisce i percorsi correttamente per la piattaforma corrente:

python
import os
 
# Costruisce un percorso verso un file in una sottodirectory
data_dir = 'data'
filename = 'users.txt'
filepath = os.path.join(data_dir, filename)
 
print(f"File path: {filepath}")

Output (su Unix/Linux/macOS):

File path: data/users.txt

Output (su Windows):

File path: data\users.txt

Puoi unire più componenti:

python
import os
 
base = '/home/alice'
project = 'myapp'
subdir = 'data'
file = 'config.json'
 
full_path = os.path.join(base, project, subdir, file)
print(full_path)  # Output: /home/alice/myapp/data/config.json

Usare os.path.join() rende il tuo codice portabile tra sistemi operativi.

29.4.4) Verificare se i percorsi esistono

Prima di lavorare con file o directory, verifica che esistano:

python
import os
 
path = 'data.txt'
 
if os.path.exists(path):
    print(f"'{path}' exists")
else:
    print(f"'{path}' does not exist")

Puoi anche verificare in modo specifico se si tratta di file o directory:

python
import os
 
path = 'mydir'
 
if os.path.isfile(path):
    print(f"'{path}' is a file")
elif os.path.isdir(path):
    print(f"'{path}' is a directory")
elif os.path.exists(path):
    print(f"'{path}' exists but is neither a file nor directory")
else:
    print(f"'{path}' does not exist")

Questi controlli prevengono errori quando provi ad aprire file inesistenti o a elencare directory inesistenti.

29.4.5) Ottenere percorsi assoluti

os.path.abspath() converte i percorsi relativi in percorsi assoluti:

python
import os
 
relative_path = 'data/users.txt'
absolute_path = os.path.abspath(relative_path)
 
print(f"Relative: {relative_path}")
print(f"Absolute: {absolute_path}")

Output (esempio):

Relative: data/users.txt
Absolute: /home/alice/projects/myapp/data/users.txt

Questo è utile per il logging, i messaggi di errore o quando devi conoscere la posizione esatta di un file.

29.4.6) Suddividere i percorsi in componenti

os.path.split() separa un percorso in directory e nome file:

python
import os
 
path = '/home/alice/projects/data.txt'
directory, filename = os.path.split(path)
 
print(f"Directory: {directory}")
print(f"Filename: {filename}")

Output:

Directory: /home/alice/projects
Filename: data.txt

os.path.basename() ottiene solo il nome file, e os.path.dirname() ottiene solo la directory:

python
import os
 
path = '/home/alice/projects/data.txt'
 
print(f"Basename: {os.path.basename(path)}")  # Output: data.txt
print(f"Dirname: {os.path.dirname(path)}")    # Output: /home/alice/projects

29.4.7) Suddividere le estensioni dei file

os.path.splitext() separa il nome del file dalla sua estensione:

python
import os
 
filename = 'report.pdf'
name, extension = os.path.splitext(filename)
 
print(f"Name: {name}")        # Output: report
print(f"Extension: {extension}")  # Output: .pdf

Questo è utile per elaborare file in base al loro tipo:

python
import os
 
files = ['data.csv', 'image.png', 'document.txt', 'script.py']
 
for file in files:
    name, ext = os.path.splitext(file)
    if ext == '.csv':
        print(f"Process CSV file: {file}")
    elif ext == '.png':
        print(f"Process image file: {file}")

Output:

Process CSV file: data.csv
Process image file: image.png

29.5) Elencare, creare e rimuovere file e directory

Il modulo os fornisce funzioni per manipolare il file system: elencare il contenuto delle directory, creare nuove directory e rimuovere file e cartelle.

29.5.1) Elencare il contenuto di una directory

os.listdir() restituisce una lista(list) di tutti gli elementi in una directory:

python
import os
 
# Elenca il contenuto della directory corrente
contents = os.listdir('.')
print("Current directory contents:")
for item in contents:
    print(f"  {item}")

Output (esempio):

Current directory contents:
  script.py
  data.txt
  mydir
  README.md

La lista(list) include sia file sia directory. Per distinguerli:

python
import os
 
contents = os.listdir('.')
print("Files:")
for item in contents:
    if os.path.isfile(item):
        print(f"  {item}")
 
print("\nDirectories:")
for item in contents:
    if os.path.isdir(item):
        print(f"  {item}")

Output:

Files:
  script.py
  data.txt
  README.md
 
Directories:
  mydir

29.5.2) Creare directory

os.mkdir() crea una singola directory:

python
import os
 
new_dir = 'output'
 
if not os.path.exists(new_dir):
    os.mkdir(new_dir)
    print(f"Created directory: {new_dir}")
else:
    print(f"Directory already exists: {new_dir}")

Output:

Created directory: output

Importante: os.mkdir() fallisce se la directory padre non esiste. Per esempio, provare a creare 'data/output' quando 'data' non esiste genererà un errore.

os.makedirs() crea tutte le directory padre necessarie:

python
import os
 
nested_dir = 'data/processed/2024'
 
if not os.path.exists(nested_dir):
    os.makedirs(nested_dir)
    print(f"Created directory structure: {nested_dir}")

Output:

Created directory structure: data/processed/2024

Questo crea data, poi data/processed, poi data/processed/2024 se non esistono.

29.5.3) Rimuovere file

os.remove() elimina un file:

python
import os
 
filename = 'temp.txt'
 
# Crea un file temporaneo
with open(filename, 'w') as f:
    f.write('Temporary data')
 
print(f"File exists: {os.path.exists(filename)}")  # Output: True
 
# Rimuove il file
os.remove(filename)
print(f"File exists: {os.path.exists(filename)}")  # Output: False

Avvertenza: os.remove() elimina i file in modo permanente: non vanno nel cestino.

29.5.4) Rimuovere directory

os.rmdir() rimuove una directory vuota:

python
import os
 
directory = 'empty_dir'
 
# Crea e poi rimuove una directory vuota
os.mkdir(directory)
print(f"Created: {directory}")
 
os.rmdir(directory)
print(f"Removed: {directory}")

os.rmdir() fallisce se la directory contiene file. Per rimuovere una directory e tutto il suo contenuto, devi prima eliminare i file:

python
import os
 
def remove_directory_contents(directory):
    """Rimuove tutti i file in una directory, poi rimuove la directory.
    
    Nota: fallisce se la directory contiene sottodirectory.
    """
    if not os.path.exists(directory):
        print(f"Directory does not exist: {directory}")
        return
    
    # Rimuove tutti i file nella directory
    for item in os.listdir(directory):
        item_path = os.path.join(directory, item)
        if os.path.isfile(item_path):
            os.remove(item_path)
            print(f"Removed file: {item_path}")
    
    # Rimuove la directory ora vuota
    os.rmdir(directory)
    print(f"Removed directory: {directory}")
 
# Esempio di utilizzo
test_dir = 'test_data'
os.makedirs(test_dir, exist_ok=True)
 
# Crea alcuni file di test
with open(os.path.join(test_dir, 'file1.txt'), 'w') as f:
    f.write('test')
with open(os.path.join(test_dir, 'file2.txt'), 'w') as f:
    f.write('test')
 
# Rimuove tutto
remove_directory_contents(test_dir)

Output:

Removed file: test_data/file1.txt
Removed file: test_data/file2.txt
Removed directory: test_data

Nota: Per una rimozione di directory più complessa (incluse le sottodirectory), il modulo shutil di Python fornisce shutil.rmtree(), ma questo va oltre il nostro ambito attuale.

29.5.5) Rinominare file e directory

os.rename() rinomina o sposta file e directory:

python
import os
 
# Rinomina un file
old_name = 'draft.txt'
new_name = 'final.txt'
 
# Crea il file di test
with open(old_name, 'w') as f:
    f.write('content')
 
os.rename(old_name, new_name)
print(f"Renamed '{old_name}' to '{new_name}'")

Puoi anche spostare i file in directory diverse:

python
import os
 
# Crea directory e file
os.makedirs('source', exist_ok=True)
os.makedirs('destination', exist_ok=True)
 
with open('source/file.txt', 'w') as f:
    f.write('content')
 
# Sposta il file in una directory diversa
os.rename('source/file.txt', 'destination/file.txt')
print("Moved file to destination directory")

I moduli sys e os danno ai tuoi programmi Python la capacità di interagire con il sistema operativo, accettare input da riga di comando, leggere la configurazione e gestire file e directory. Queste capacità trasformano script semplici in potenti strumenti da riga di comando che si integrano senza problemi con l’ambiente di sistema più ampio.


© 2025. Primesoft Co., Ltd.
support@primesoft.ai