Il modulo `io` in Python
Questo articolo spiega il modulo io in Python.
Spiegheremo il modulo io in Python con esempi pratici.
YouTube Video
Il modulo io in Python
L'elaborazione di input/output costituisce la base per ogni tipo di operazione sui dati, come file, reti e I/O standard. Il modulo io di Python fornisce una serie di classi astratte che unificano queste operazioni di input/output. Il concetto chiave per comprendere questo modulo è l'idea di "stream" (flusso).
Cos'è uno stream?
Uno stream è un flusso astratto per leggere e scrivere dati in modo sequenziale e continuo.
Quando si leggono i contenuti dei file byte per byte o si inviano e ricevono dati tramite rete, tutte queste operazioni possono essere gestite come stream di dati.
Astrarre questo meccanismo permette di gestire con operazioni comuni come lettura e scrittura file, memoria e reti—diverse fonti di I/O.
Il modulo io di Python fornisce un'interfaccia unificata per gli stream, consentendo una gestione efficiente sia dei dati testuali che binari.
Struttura di base del modulo io
Il modulo io presenta una gerarchia a tre livelli a seconda della natura degli stream.
-
Livello grezzo (
RawIOBase)RawIOBasegestisce l'I/O di byte a livello più basso, come i file descriptor del sistema operativo e i dispositivi. -
Livello bufferizzato (
BufferedIOBase)BufferedIOBasefornisce una cache (buffer) per migliorare l'efficienza dell'I/O.BufferedReadereBufferedWritersono esempi tipici. -
Livello di testo (
TextIOBase)TextIOBaseconverte sequenze di byte in stringhe e gestisce l'encoding. Di solito, aprendo un file con la funzioneopen(), si utilizzaTextIOWrapperdi questo livello.
Grazie a questa struttura, il modulo io separa chiaramente I/O testuale e binario permettendo combinazioni flessibili.
Struttura di base del modulo io
RawIOBase gestisce i file descriptor del sistema operativo nel livello più basso, BufferedIOBase aggiunge una cache sopra, e il livello superiore TextIOBase si occupa della conversione delle stringhe.
1import io
2
3# Check the core base classes hierarchy
4print(io.IOBase.__subclasses__())- Questo codice serve per verificare il gruppo di classi astratte che eredita da
IOBase. Si possono vedereTextIOBase,BufferedIOBaseeRawIOBase, confermando la struttura gerarchica.
io.IOBase: La classe base di tutte
IOBase è la classe astratta base per tutti gli oggetti di I/O, e definisce metodi comuni come close(), flush() e seekable(). Viene raramente usata direttamente e di solito si accede tramite le classi derivate.
1import io
2
3f = io.StringIO("data")
4print(f.seekable()) # True
5print(f.readable()) # True
6print(f.writable()) # True
7f.close()- Questo esempio mostra che i metodi comuni di
IOBasepossono essere usati anche nelle classi superiori.seekable()ereadable()sono utili per verificare le proprietà di uno stream.
io.RawIOBase: Il livello più basso
RawIOBase è il livello più vicino ai file descriptor del sistema operativo e non effettua buffering. L'implementazione tipica è FileIO, che legge e scrive per byte.
1import io, os
2
3# Create a low-level FileIO object (no buffering)
4fd = os.open('raw_demo.bin', os.O_RDWR | os.O_CREAT)
5raw = io.FileIO(fd, mode='w+')
6raw.write(b'abc123')
7raw.seek(0)
8print(raw.read(6)) # b'abc123'
9raw.close()FileIOè una implementazione concreta diRawIOBase; tutte le letture e scritture sono eseguite comebytes. L'efficienza può essere migliorata combinandola con il livello superioreBufferedIOBase.
io.BufferedIOBase: Livello intermedio (con buffering)
BufferedIOBase è uno strato intermedio che esegue buffering, rendendo l'accesso al disco più efficiente. Le principali implementazioni sono BufferedReader, BufferedWriter, BufferedRandom e BufferedRWPair.
1import io
2
3# Create a buffered binary stream on top of a BytesIO (simulate file)
4base = io.BytesIO()
5buffered = io.BufferedWriter(base)
6buffered.write(b'Python IO buffering')
7buffered.flush()
8base.seek(0)
9print(base.read()) # b'Python IO buffering'- In questo esempio, i dati scritti tramite
BufferedWritervengono temporaneamente memorizzati in un buffer di memoria e trasferiti effettivamente al livello inferiore quando si chiamaflush().
Esempio di BufferedReader
BufferedReader è uno stream bufferizzato di sola lettura che supporta una lettura efficiente con peek() e read().
1import io
2
3stream = io.BytesIO(b"1234567890")
4reader = io.BufferedReader(stream)
5print(reader.peek(5)) # b'12345' (non-destructive)
6print(reader.read(4)) # b'1234'
7print(reader.read(3)) # b'567'peek()si limita a "sbirciare" i dati e non sposta il puntatore. Combinandolo conread()si può controllare il buffering in modo flessibile.
io.TextIOBase: Livello solo testo
TextIOBase è un livello di astrazione per la gestione delle stringhe, eseguendo internamente la decodifica e la codifica. Una classe di implementazione tipica è TextIOWrapper.
1import io
2
3# Wrap a binary stream to handle text encoding
4binary = io.BytesIO()
5text_stream = io.TextIOWrapper(binary, encoding='utf-8')
6text_stream.write("\u3053\u3093\u306B\u3061\u306F")
7text_stream.flush()
8
9# Reset stream position
10binary.seek(0)
11
12# Read bytes once
13data = binary.read()
14
15# Show both raw bytes and decoded text
16print("Raw bytes:", data)
17print("Decoded text:", data.decode('utf-8'))- In questo esempio,
TextIOWrappercodifica la stringa in UTF-8 e la scrive nello stream binario sottostante.
Esempio di lettura con TextIOWrapper
La decodifica viene eseguita automaticamente durante la lettura.
1import io
2
3binary_data = io.BytesIO("Python I/O".encode('utf-8'))
4text_reader = io.TextIOWrapper(binary_data, encoding='utf-8')
5print(text_reader.read()) # 'Python I/O'TextIOWrapperfunge da classe fondamentale per l'I/O di testo e costituisce la base per quasi tutte le operazioni su file di alto livello.
io.StringIO: Stream di testo in memoria
StringIO è una classe che consente di gestire stringhe in memoria come se fossero file. È utile per testare operazioni di I/O e generare dati temporanei.
1import io
2
3text_buf = io.StringIO()
4text_buf.write("In-memory text stream")
5text_buf.seek(0)
6print(text_buf.read()) # 'In-memory text stream'StringIOconsente operazioni analoghe ai file senza usare il disco ed è molto usato nei test unitari.
io.BytesIO: Stream binario in memoria
BytesIO è una classe file in memoria per gestire sequenze di byte (bytes). È utile in situazioni come l'elaborazione binaria o la compressione dati in cui non si vuole usare file.
1import io
2
3buf = io.BytesIO()
4buf.write(b'\x01\x02\x03')
5buf.seek(0)
6print(list(buf.read())) # [1, 2, 3]BytesIOha la stessa interfaccia diBufferedIOBasee può essere usata come sostituto di molte API di file.
Stream personalizzati (creazione di classi originali)
Le classi nel modulo io sono estendibili, permettendo di creare le proprie classi di stream. Di seguito un esempio di sottoclasse di TextIOBase che converte in maiuscolo tutto il testo in scrittura.
1import io
2
3class UpperTextIO(io.TextIOBase):
4 def __init__(self):
5 self.buffer = ""
6 def write(self, s):
7 self.buffer += s.upper()
8 return len(s)
9
10u = UpperTextIO()
11u.write("hello io")
12print(u.buffer) # "HELLO IO"- Finché si rispetta il contratto di
TextIOBase, si può definire qualsiasi comportamento personalizzato come questo. È inoltre facile estendere gli stream per usi specifici, come file e reti.
Riepilogo
Il modulo io organizza la gestione dell'input/output in una gerarchia di classi astratte e concrete.
RawIOBaseè una classe per l'I/O di byte a livello di sistema operativo.BufferedIOBaseè una classe che fornisce uno strato cache efficiente.TextIOBaseè una classe che gestisce la lettura e la scrittura di stringhe.StringIOeBytesIOsono classi che forniscono stream in memoria.
Comprendere queste classi permette di cogliere appieno il funzionamento del sistema di I/O di Python e applicarlo alle operazioni su file, comunicazione di rete e progettazione di stream per test.
Puoi seguire l'articolo sopra utilizzando Visual Studio Code sul nostro canale YouTube. Controlla anche il nostro canale YouTube.