Modulen `io` i Python

Modulen `io` i Python

Den här artikeln förklarar modulen io i Python.

Vi kommer att förklara modulen io i Python med praktiska exempel.

YouTube Video

Modulen io i Python

In- och utmatningshantering utgör grunden för alla typer av dataoperationer, såsom filer, nätverk och standard I/O. Pythons modul io tillhandahåller en uppsättning abstrakta klasser som förenar dessa in- och utmatningsoperationer. Det viktigaste konceptet för att förstå denna modul är idén om ett "flöde" (stream).

Vad är en ström?

Ett flöde är ett abstrakt sätt att läsa och skriva data sekventiellt och kontinuerligt.

När man läser filinnehåll byte för byte eller skickar och tar emot data över ett nätverk kan allt detta hanteras som dataströmmar.

Genom att abstrahera denna mekanism kan filer, minne och nätverk – olika källor till I/O – hanteras med gemensamma operationer såsom läsning och skrivning.

Pythons modul io tillhandahåller ett enhetligt gränssnitt för strömmar, vilket möjliggör effektiv hantering av både text och binär data.

Grundläggande struktur för modulen io

Modulen io har en trelagershierarki beroende på typen av strömmar.

  1. Rått lager (RawIOBase)

    RawIOBase hanterar den lägsta nivån för byte I/O, såsom operativsystemets fildeskriptorer och enheter.

  2. Buffrat lager (BufferedIOBase)

    BufferedIOBase tillhandahåller en cache (buffert) för att öka I/O-effektiviteten. BufferedReader och BufferedWriter är typiska exempel.

  3. Textlager (TextIOBase)

    TextIOBase konverterar byte-sekvenser till strängar och hanterar kodning (encoding). Vanligtvis, när man öppnar en fil med funktionen open(), används TextIOWrapper från detta lager.

Tack vare denna struktur separerar modulen io tydligt text- och binär-I/O samtidigt som flexibla kombinationer är möjliga.

Grundläggande struktur för modulen io

RawIOBase hanterar operativsystemets fildeskriptorer på den lägsta nivån, sedan lägger BufferedIOBase till en cache, och det översta lagret, TextIOBase, hanterar strängkonverteringar.

1import io
2
3# Check the core base classes hierarchy
4print(io.IOBase.__subclasses__())
  • Denna kod används för att kontrollera gruppen av abstrakta klasser som ärver från IOBase. Du kan se TextIOBase, BufferedIOBase och RawIOBase, vilket bekräftar den hierarkiska strukturen.

io.IOBase: Bas-klassen för alla

IOBase är den abstrakta basklassen för alla I/O-objekt och definierar gemensamma metoder såsom close(), flush() och seekable(). Den används sällan direkt och nås vanligtvis via subklasser.

1import io
2
3f = io.StringIO("data")
4print(f.seekable())   # True
5print(f.readable())   # True
6print(f.writable())   # True
7f.close()
  • Detta exempel visar att de gemensamma metoderna hos IOBase även kan användas i högre liggande klasser. seekable() och readable() är användbara för att kontrollera egenskaperna hos en ström.

io.RawIOBase: Det lägsta lagret

RawIOBase är det lager som ligger närmast operativsystemets fildeskriptor och utför ingen buffring. Den typiska implementeringen är FileIO, som läser och skriver byte för 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 är en konkret implementering av RawIOBase; all läsning och skrivning sker som bytes. Effektiviteten kan förbättras om man kombinerar det med det högre lagret BufferedIOBase.

io.BufferedIOBase: Mellanlager (med buffring)

BufferedIOBase är ett mellanlager som utför buffring, vilket gör diskåtkomst mer effektiv. De viktigaste implementeringarna är BufferedReader, BufferedWriter, BufferedRandom och 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'
  • I det här exemplet lagras data som skrivs via BufferedWriter temporärt i en minnesbuffert och överförs faktiskt till det undre lagret när man anropar flush().

Exempel på BufferedReader

BufferedReader är en skrivskyddad buffrad ström som stöder effektiv läsning med peek() och 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() "kikar" bara på datan och flyttar inte pekaren. Genom att kombinera den med read() kan du flexibelt styra buffringen.

io.TextIOBase: Endast text-lager

TextIOBase är ett abstraktionslager för att hantera strängar, som internt utför avkodning och kodning. En typisk implementering är 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'))
  • I det här exemplet kodar TextIOWrapper strängen till UTF-8 och skriver den till den underliggande binära strömmen.

Exempel på läsning med TextIOWrapper

Dekodning sker automatiskt vid läsning.

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'
  • TextIOWrapper fungerar som grundklassen för text-I/O och utgör basen för nästan alla avancerade filoperationer.

io.StringIO: Textström i minnet

StringIO är en klass som låter dig hantera strängar i minnet som om de vore filer. Den är användbar för I/O-testning och tillfällig datagenerering.

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'
  • StringIO möjliggör fil-liknande operationer utan att använda disken och används ofta i enhetstester.

io.BytesIO: Binärström i minnet

BytesIO är en minnesbaserad filklass för hantering av byte-sekvenser (bytes). Den är användbar för situationer som binärhantering eller datakomprimering där man inte vill använda filer.

1import io
2
3buf = io.BytesIO()
4buf.write(b'\x01\x02\x03')
5buf.seek(0)
6print(list(buf.read()))  # [1, 2, 3]
  • BytesIO har samma gränssnitt som BufferedIOBase och kan användas som ersättning för många fil-API:er.

Egna strömmar (skapa egna klasser)

Klasserna i io är utbyggbara, vilket gör att du kan skapa egna strömklasser. Nedan finns ett exempel på en subklass till TextIOBase som skriver all text med versaler.

 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"
  • Så länge du följer kontraktet för TextIOBase kan du definiera valfritt eget beteende på detta sätt. Det är också enkelt att utöka strömmar för särskilda ändamål, såsom filer och nätverk.

Sammanfattning

Modulen io organiserar in- och utmatningshantering i en hierarki av abstrakta och konkreta klasser.

  • RawIOBase är en klass för byte-I/O på operativsystemnivå.
  • BufferedIOBase är en klass som tillhandahåller ett effektivt cache-lager.
  • TextIOBase är en klass som hanterar läsning och skrivning av strängar.
  • StringIO och BytesIO är klasser som tillhandahåller minnesströmmar.

Genom att förstå dessa klasser kan du noggrant förstå hur Pythons I/O-system fungerar och tillämpa dem på filoperationer, nätverkskommunikation och design av testströmmar.

Du kan följa med i artikeln ovan med hjälp av Visual Studio Code på vår YouTube-kanal. Vänligen kolla även in YouTube-kanalen.

YouTube Video