← Lekcje
Python · lekcja 15

Pliki: czytanie i zapis

  1. Po co plik: dane zostają po zamknięciu programu
  2. with open(...): nazwa, tryb, kodowanie UTF-8
  3. Tryby r, w, a oraz funkcje read i write
  4. Ćwiczenie: lista zakupów zapisana w pliku i policzona
Rozgrzewka · 3 minuty

Co pamiętacie z lekcji 14?

  1. Czym różni się słownik od listy?
  2. Jak dodać do słownika prices parę: klucz „ser”, wartość 12.0?
  3. Co sprawdza zapis "chleb" in prices?
Część 1 · Po co plik

Dane, które zostają po zamknięciu programu

Zmienne i słowniki żyją tylko tak długo, jak działa program: po jego zakończeniu pamięć jest sprzątana i dane znikają. Plik to miejsce na dysku, które zostaje. Zmienna jest jak to, co pamiętacie w czasie lekcji, a plik jak zeszyt, który zabieracie do domu.

Program (pamięć) shopping = ["chleb", "mleko"] znika po zakończeniu Plik na dysku shopping.txt zostaje po wyłączeniu zapis: write odczyt: read

Plik otwiera funkcja open. W nawiasie podajemy nazwę pliku, tryb (co zamierzamy z nim zrobić) i kodowanie: open(nazwa, tryb, encoding=...).

docs.python.org, The Python Tutorial, rozdz. 7.2 (Reading and Writing Files)
Część 1 · with open

Trzy rzeczy w nawiasie: nazwa, tryb, kodowanie

with open("notes.txt", "w", encoding="utf-8") as f:
    f.write("Ala\n")

print(f.closed)

Na ekranie: True

  • "notes.txt" to nazwa pliku, "w" to tryb, czyli zamiar: zapis.
  • as f nadaje nazwę uchwytowi: przez f sięgamy do pliku, a nie do jego treści.
  • with zamyka plik po wyjściu z bloku, także wtedy, gdy program zgłosi błąd.

W praktyce: dopisanie litery b do trybu ("rb", "wb") otwiera plik binarny: dane są wtedy bajtami, a kodowania nie podaje się wcale. Tak czyta się zdjęcia i pliki muzyczne.

docs.python.org, The Python Tutorial, rozdz. 7.2 (Reading and Writing Files)
Część 2 · Zapis

write pisze dokładnie to, co dostanie

Z \n na końcu

with open("notes.txt", "w", encoding="utf-8") as f:
    f.write("Ala\n")
    f.write("Ola\n")

W pliku: Ala i Ola w dwóch liniach

Bez \n

with open("notes.txt", "w", encoding="utf-8") as f:
    f.write("Ala")
    f.write("Ola")

W pliku: AlaOla w jednej linii

Znak \n to znak nowej linii: w pliku tekstowym on jeden decyduje, gdzie kończy się linia. Funkcja write oddaje liczbę zapisanych znaków, więc f.write("Ala\n") daje 4.

docs.python.org, The Python Tutorial, rozdz. 7.2.1 (Methods of File Objects)
Część 2 · Tryby otwarcia

Trzy litery, trzy różne skutki

TrybCo robiGdy pliku nie ma
"r"tylko czytanie, tryb domyślnybłąd FileNotFoundError
"w"tylko zapis, stara zawartość zostaje wymazanatworzy nowy plik
"a"dopisanie: nowe dane trafiają na koniectworzy nowy plik
plik przed chleb mleko tryb "w" write("ser") po zapisie ser reszta wymazana plik przed chleb mleko tryb "a" write("ser") po zapisie chleb mleko ser
docs.python.org, The Python Tutorial, rozdz. 7.2 (Reading and Writing Files)
Część 3 · Czytanie

Cały plik naraz albo lista linii

with open("notes.txt", "r", encoding="utf-8") as f:
    text = f.read()
print(text, end="")

Na ekranie:
Ala
Ola

with open("notes.txt", "r", encoding="utf-8") as f:
    lines = f.readlines()
print(lines)

Na ekranie:
['Ala\n', 'Ola\n']

Funkcja read oddaje całą zawartość jako jeden napis. Funkcja readlines oddaje listę: jeden element to jedna linia, razem ze znakiem \n na końcu.

docs.python.org, The Python Tutorial, rozdz. 7.2.1 (Methods of File Objects)
Część 3 · Linia po linii

Pętla po pliku i licznik linii

count = 0
with open("shopping.txt", "r", encoding="utf-8") as f:
    for line in f:
        print(line, end="")
        count = count + 1

print("Produktów:", count)

Na ekranie:

chleb
mleko
jabłka
Produktów: 3

Bez end="" między produktami pojawiłyby się puste linie: linia z pliku ma już swój \n, a print dołożyłby drugi.

W praktyce: słownika nie zapisuje się do pliku ręcznie. Moduł json robi to jednym poleceniem: json.dump(prices, f) zapisuje, a json.load(f) odczytuje i oddaje gotowy słownik.

docs.python.org, The Python Tutorial, rozdz. 7.2.1 (Methods of File Objects) · rozdz. 7.2.2 (Saving structured data with json)
Ćwiczenie · przy komputerze · 12 minut

Ćwiczenie: lista zakupów w pliku

  1. Napisz program save.py: zapisz do pliku shopping.txt trzy produkty, każdy w osobnej linii. Uruchom go i otwórz plik w edytorze.
  2. Napisz program show.py: wczytaj cały plik funkcją read do zmiennej text i wypisz go na ekran.
  3. Dopisz w show.py licznik linii i wypisz „Produktów: …”. Potem dopisz do pliku czwarty produkt trybem "a" i uruchom program jeszcze raz.
Jak to sprawdzić

Uruchom save.py dwa razy pod rząd: plik dalej ma trzy linie, bo tryb "w" za każdym razem kasuje starą zawartość. Uruchom dopisanie dwa razy: linii jest pięć, bo tryb "a" nic nie kasuje.

Sprawdzenie

Trzy pytania na koniec

  1. Po co otwieramy plik zapisem with open(...), zamiast samym open(...)?
  2. Czym różni się tryb "w" od trybu "a"?
  3. Dlaczego przy wypisywaniu linii z pliku piszemy print(line, end="")?
Podsumowanie

A jak to wygląda w produkcji?

Na lekcjiW produkcjiStatus
with open(...)Program zamyka plik nawet po błędzie, więc zapis nie urywa się w połowiestandard
Tryb "a"Dziennik zdarzeń serwera dopisuje kolejne linie na koniec i nigdy nie kasuje starychcodziennie
encoding="utf-8"Jedno kodowanie w całym projekcie, żeby „ó” nie zmieniło się w krzaczki na innym systemiestandard
Pętla for line in fPliki z milionami linii czyta się po jednej, bo cała zawartość nie mieści się w pamięciprzy dużych danych