2.27. Odczyt i zapis

Pliki żyją na dysku; Python dociera do nich przez open(), która zwraca obiekt pliku, którego metody odczytują i zapisują leżące u podstaw bajty.

2.27.1. open i tryby

Pierwszym argumentem jest ścieżka; drugim jest tryb – krótki łańcuch mówiący Pythonowi, jak plik będzie używany:

  • "r" – odczyt (domyślnie). Otwiera istniejący plik do odczytu.

  • "w" – zapis. Tworzy nowy plik lub obcina istniejący do pustego.

  • "a" – dopisywanie. Otwiera plik do zapisu na jego końcu bez obcinania.

  • "b" dodane do dowolnego z powyższych ("rb", "wb", "ab") – tryb binarny. Zawartością pliku jest bytes, a nie str.

f = open("notes.txt", "r")
text = f.read()
f.close()

2.27.2. Używaj menedżera kontekstu

Powyższy wzorzec wycieka uchwyt do pliku, jeśli cokolwiek między open() a close zgłosi wyjątek. Rozwiązaniem jest instrukcja with (zobacz menedżery kontekstu):

with open("notes.txt") as f:
    text = f.read()

# f is closed here, even if read() failed

To jest standardowa postać – zapisuj to tak za każdym razem.

2.27.3. Odczyt

Obiekty plików obsługują kilka stylów odczytu:

  • io.IOBase.read() – odczytuje cały plik (lub N bajtów) i zwraca go jako pojedynczy łańcuch (lub obiekt bytes).

  • io.IOBase.readline() – odczytuje jeden wiersz wraz z końcowym "\n".

  • Bezpośrednia iteracja po pliku zwraca wiersze po jednym naraz, przy znacznie mniejszym zużyciu pamięci niż odczyt całego pliku za jednym razem.

with open("log.txt") as f:
    for line in f:
        print(line.rstrip())

str.rstrip() usuwa końcowy znak nowej linii przed wypisaniem, dzięki czemu wynik nie jest podwójnie odstępowany.

2.27.4. Zapis

Otwórz plik w trybie "w" i użyj io.IOBase.write():

with open("out.txt", "w") as f:
    f.write("hello\n")
    f.write("world\n")

io.IOBase.write() nie dodaje znaku nowej linii – zapisuje dokładnie te bajty (lub znaki, w trybie tekstowym), które mu przekażesz.

2.27.5. Tekst kontra dane binarne

Tryb tekstowy (domyślny, "r" / "w" bez "b") dekoduje przychodzące bajty na str przy użyciu domyślnego kodowania i koduje wychodzący str z powrotem na bajty. Używaj go do konfiguracji, logów, JSON-a – wszystkiego, co jest tekstem.

Tryb binarny ("rb" / "wb") pomija etap dekodowania i zwraca bytes. Używaj go do obrazów, rekordów spakowanych strukturą, przechwyceń sieciowych – wszędzie tam, gdzie liczy się każdy bajt, a plik nie jest czytelny dla człowieka.

2.27.6. Listowanie i usuwanie plików

Moduł os udostępnia operacje na systemie plików, których nie ma na samym obiekcie pliku:

import os

for name in os.listdir("/"):
    print(name)

Otaczaj te operacje przechwytywaniem OSError, gdy plik lub katalog może nie istnieć – ta operacja jest jednym z częstych miejsc, w których wyjątki pojawiają się w rzeczywistych skryptach.