Odczyt i zapis plików txt i csv, kontekst with open(), kodowanie UTF-8.
Plik otwieramy funkcją open(nazwa, tryb, encoding). Zawsze powinniśmy go zamknąć po skończeniu — najlepiej używając menedżera kontekstu with.
| Tryb | Znaczenie | Plik nie istnieje |
|---|---|---|
'r' | odczyt (domyślny) | FileNotFoundError |
'w' | zapis — nadpisuje | tworzy nowy |
'a' | dopisywanie na koniec | tworzy nowy |
'x' | tworzenie — błąd gdy istnieje | tworzy nowy |
'r+' | odczyt i zapis | FileNotFoundError |
'rb' | odczyt binarny | FileNotFoundError |
'wb' | zapis binarny | tworzy nowy |
with automatycznie zamyka plik po wyjściu z bloku — nawet gdy wystąpi błąd. Bez with musisz pamiętać o plik.close().
# Bez with — ryzykowne
plik = open("dane.txt", "r", encoding="utf-8")
zawartosc = plik.read()
plik.close() # trzeba pamiętać!
# Z with — zalecane
with open("dane.txt", "r", encoding="utf-8") as plik:
zawartosc = plik.read()
# plik zamknięty automatycznie po wyjściu z bloku
# Tryb zapisu — tworzy lub nadpisuje
with open("wynik.txt", "w", encoding="utf-8") as plik:
plik.write("Hello, World!\n")
# Tryb dopisywania
with open("log.txt", "a", encoding="utf-8") as plik:
plik.write("Nowa linia\n")
# Plik w podkatalogu
with open("dane/uczniowie.txt", "r", encoding="utf-8") as f:
dane = f.read()
| Metoda | Zwraca | Kiedy używać |
|---|---|---|
read() | cały plik jako str | małe pliki, cały tekst naraz |
read(n) | n znaków | czytanie fragmentów |
readline() | jedna linia jako str | linia po linii ręcznie |
readlines() | lista wszystkich linii | gdy potrzebna lista |
for linia in plik | iterator linii | duże pliki, oszczędność pamięci |
\n. Przy odczycie readline() i iteracji ten znak zostaje. Usuń go przez linia.strip() lub linia.rstrip('\n').
# read() — cały plik naraz
with open("tekst.txt", "r", encoding="utf-8") as f:
zawartosc = f.read()
print(zawartosc)
# readlines() — lista linii (z \n)
with open("tekst.txt", "r", encoding="utf-8") as f:
linie = f.readlines()
print(linie) # ['linia1\n', 'linia2\n', ...]
# Iteracja — linia po linii (najczęściej używane)
with open("tekst.txt", "r", encoding="utf-8") as f:
for linia in f:
linia = linia.strip() # usuwa \n i spacje
if linia: # pomija puste linie
print(linia)
# readline() — ręcznie
with open("tekst.txt", "r", encoding="utf-8") as f:
pierwsza = f.readline().strip()
druga = f.readline().strip()
print(pierwsza, druga)
write(tekst) — zapisuje dokładnie podany tekst. Nie dodaje automatycznie nowej linii — musisz dopisać \n samodzielnie.
writelines(lista) — zapisuje listę napisów. Też nie dodaje \n między elementami.
write() zwraca liczbę zapisanych znaków'w' kasuje poprzednią zawartość pliku'a' dopisuje na koniec — nie kasujeencoding="utf-8" dla polskich znakówflush(). Blok with automatycznie wywołuje flush() i close() przy wyjściu.
# Zapis pojedynczych linii
with open("wyniki.txt", "w", encoding="utf-8") as f:
f.write("Wyniki egzaminu\n")
f.write("=" * 20 + "\n")
f.write(f"Kasia: 95\n")
f.write(f"Marek: 87\n")
# Zapis listy — writelines
uczniowie = ["Kasia", "Marek", "Zofia", "Piotr"]
with open("lista.txt", "w", encoding="utf-8") as f:
for i, u in enumerate(uczniowie, 1):
f.write(f"{i}. {u}\n")
# Dopisywanie — tryb 'a'
with open("log.txt", "a", encoding="utf-8") as f:
import datetime
znacznik = datetime.datetime.now()
f.write(f"{znacznik}: Program uruchomiony\n")
# Zapis z użyciem print() do pliku
with open("raport.txt", "w", encoding="utf-8") as f:
print("Raport", file=f)
print("-" * 20, file=f)
print(f"Suma: {100}", file=f)
CSV (Comma-Separated Values) to format pliku tekstowego gdzie dane rozdzielone są przecinkami (lub średnikami). Pierwsza linia to zazwyczaj nagłówek.
csv jest wbudowany — nie trzeba instalowaćcsv.reader — odczyt jako listy wierszycsv.writer — zapis list jako wierszy CSVcsv.DictReader — odczyt jako słowniki (klucz = nagłówek)csv.DictWriter — zapis słownikówdelimiter — separator (domyślnie ',')newline='' — bez tego moduł csv może nieprawidłowo obsługiwać znaki nowej linii, szczególnie na Windows.
import csv
# Zapis CSV
dane = [
["Imię", "Klasa", "Punkty"],
["Kasia", "3A", 95],
["Marek", "3B", 87],
["Zofia", "3A", 91],
]
with open("uczniowie.csv", "w", newline="",
encoding="utf-8") as f:
writer = csv.writer(f)
writer.writerows(dane)
# Odczyt CSV — reader
with open("uczniowie.csv", "r", newline="",
encoding="utf-8") as f:
reader = csv.reader(f)
naglowek = next(reader) # pierwsza linia = nagłówek
for wiersz in reader:
print(wiersz)
# Odczyt CSV — DictReader (wygodniejszy)
with open("uczniowie.csv", "r", newline="",
encoding="utf-8") as f:
reader = csv.DictReader(f)
for wiersz in reader:
print(f"{wiersz['Imię']}: {wiersz['Punkty']}")
Operacje na plikach mogą się nie powieść z wielu powodów. Dobrze napisany program obsługuje te sytuacje zamiast się zawieszać.
| Wyjątek | Przyczyna |
|---|---|
FileNotFoundError | plik nie istnieje (tryb 'r') |
PermissionError | brak uprawnień do pliku |
IsADirectoryError | podano katalog zamiast pliku |
UnicodeDecodeError | złe kodowanie znaków |
IOError | ogólny błąd wejścia/wyjścia |
import os — os.path.exists(nazwa) sprawdza czy plik istnieje. os.path.isfile() sprawdza czy to plik (nie katalog). Pozwala uniknąć wyjątku zamiast go łapać.
import os
nazwa = input("Nazwa pliku: ")
# Sprawdzenie przed otwarciem
if not os.path.exists(nazwa):
print(f"Plik '{nazwa}' nie istnieje.")
else:
with open(nazwa, "r", encoding="utf-8") as f:
print(f.read())
# Obsługa wyjątkami
try:
with open(nazwa, "r", encoding="utf-8") as f:
zawartosc = f.read()
print(zawartosc)
except FileNotFoundError:
print(f"Błąd: plik '{nazwa}' nie istnieje.")
except PermissionError:
print("Błąd: brak uprawnień do odczytu.")
except UnicodeDecodeError:
print("Błąd: sprawdź kodowanie pliku.")
except Exception as e:
print(f"Nieoczekiwany błąd: {e}")
finally:
print("Operacja zakończona.")
Poniżej najczęstsze scenariusze z egzaminów INF.04 — zapamiętaj te wzorce.
int() lub float()encoding="utf-8" — polskie znaki (ą, ę, ó...) wymagają UTF-8. Bez tego dostaniesz UnicodeDecodeError lub przekłamania w tekście.
# Wzorzec 1: wczytaj liczby z pliku, oblicz sumę
with open("liczby.txt", "r", encoding="utf-8") as f:
liczby = [int(linia.strip()) for linia in f
if linia.strip()]
print(f"Suma: {sum(liczby)}, Avg: {sum(liczby)/len(liczby):.2f}")
# Wzorzec 2: wczytaj CSV bez modułu csv
wyniki = []
with open("dane.csv", "r", encoding="utf-8") as f:
naglowek = f.readline() # pomiń nagłówek
for linia in f:
czesci = linia.strip().split(",")
imie = czesci[0]
wynik = int(czesci[1])
wyniki.append((imie, wynik))
# Wzorzec 3: zlicz linie, słowa, znaki
with open("tekst.txt", "r", encoding="utf-8") as f:
tekst = f.read()
linie = tekst.splitlines()
slowa = tekst.split()
print(f"Linii: {len(linie)}, Słów: {len(slowa)}, Znaków: {len(tekst)}")
# Wzorzec 4: zapisz posortowane wyniki
wyniki.sort(key=lambda x: x[1], reverse=True)
with open("ranking.txt", "w", encoding="utf-8") as f:
for i, (imie, w) in enumerate(wyniki, 1):
f.write(f"{i}. {imie}: {w}\n")
Wczytuj od użytkownika pary: imię ucznia i ocena. Zapisz je do pliku oceny.txt (każda para w osobnej linii, oddzielona przecinkiem). Następnie odczytaj plik i wypisz wszystkich uczniów z ich średnią.
# CZĘŚĆ 1: Zbieranie i zapis
wpisy = []
while True:
imie = input("Imię (lub 'koniec'): ")
if imie.lower() == "koniec":
break
ocena = int(input("Ocena: "))
wpisy.append((imie, ocena))
with open("oceny.txt", "w", encoding="utf-8") as f:
for imie, ocena in wpisy:
f.write(f"{imie},{ocena}\n")
print("Zapisano do pliku oceny.txt")
# CZĘŚĆ 2: Odczyt i statystyki
uczniowie = {}
with open("oceny.txt", "r", encoding="utf-8") as f:
for linia in f:
czesci = linia.strip().split(",")
imie = czesci[0]
ocena = int(czesci[1])
if imie not in uczniowie:
uczniowie[imie] = []
uczniowie[imie].append(ocena)
print("\n--- Statystyki ---")
for imie, oceny in uczniowie.items():
sr = sum(oceny) / len(oceny)
print(f"{imie:<12} oceny: {oceny} śr: {sr:.2f}")
f.write(f"{imie},{ocena}\n") — przecinek jako separator, \n na końcu każdej linii. To prosty format CSV bez modułu csv.
linia.strip().split(",") — najpierw usuwamy \n przez strip(), potem dzielimy po przecinku. Indeks [0] to imię, [1] to ocena.
uczniowie grupuje oceny — dla każdego imienia lista ocen. Wzorzec identyczny jak w kafelku 07.
with. To ważne: między nimi plik jest poprawnie zamknięty i gotowy do odczytu.
Masz plik CSV z kolumnami: Imię, Matematyka, Polski, Angielski. Wczytaj go, oblicz średnią dla każdego ucznia i dla każdego przedmiotu. Wypisz ranking uczniów (od najlepszego) i zapisz go do nowego pliku.
import csv
# Plik wejściowy (utwórz go ręcznie lub kodem poniżej)
# Imię,Matematyka,Polski,Angielski
# Kasia,90,85,92
# Marek,78,88,75
# Zofia,95,91,89
uczniowie = []
with open("wyniki.csv", "r", newline="",
encoding="utf-8") as f:
reader = csv.DictReader(f)
for wiersz in reader:
imie = wiersz["Imię"]
mat = int(wiersz["Matematyka"])
pol = int(wiersz["Polski"])
ang = int(wiersz["Angielski"])
sr = (mat + pol + ang) / 3
uczniowie.append({
"imie": imie, "mat": mat,
"pol": pol, "ang": ang, "sr": sr
})
# Ranking uczniów
ranking = sorted(uczniowie, key=lambda x: x["sr"],
reverse=True)
print(f"{'Miejsce':<8} {'Imię':<10} {'Mat':>5} "
f"{'Pol':>5} {'Ang':>5} {'Śr':>7}")
print("-" * 45)
for i, u in enumerate(ranking, 1):
print(f"{i:<8} {u['imie']:<10} {u['mat']:>5} "
f"{u['pol']:>5} {u['ang']:>5} {u['sr']:>7.2f}")
# Zapis rankingu
with open("ranking.txt", "w", encoding="utf-8") as f:
f.write("RANKING UCZNIÓW\n")
f.write("=" * 30 + "\n")
for i, u in enumerate(ranking, 1):
f.write(f"{i}. {u['imie']}: {u['sr']:.2f}\n")
wiersz["Matematyka"] zamiast wiersz[1] — czytelniejsze i mniej podatne na błędy pozycyjne.
sorted(..., key=lambda x: x["sr"], reverse=True) — sortujemy malejąco po wartości klucza "sr" w każdym słowniku.
Wczytaj plik tekstowy. Utwórz nowy plik zawierający tylko linie które zawierają podane słowo kluczowe (wyszukiwanie bez rozróżniania wielkości liter). Wypisz ile linii skopiowano i ile pominięto.
import os
plik_we = input("Plik wejściowy: ")
plik_wy = input("Plik wyjściowy: ")
szukane = input("Słowo kluczowe: ").lower()
if not os.path.exists(plik_we):
print("Błąd: plik wejściowy nie istnieje.")
else:
skopiowano = 0
pominieto = 0
with open(plik_we, "r", encoding="utf-8") as f_we, \
open(plik_wy, "w", encoding="utf-8") as f_wy:
for linia in f_we:
if szukane in linia.lower():
f_wy.write(linia)
skopiowano += 1
else:
pominieto += 1
print(f"Skopiowano: {skopiowano} linii")
print(f"Pominięto: {pominieto} linii")
print(f"Zapisano do: {plik_wy}")
with open(...) as f_we, open(...) as f_wy: — można otworzyć wiele plików w jednym bloku with. Oba zostaną poprawnie zamknięte.
szukane in linia.lower() — zamieniamy linię na małe litery przed porównaniem. Szukane słowo też jest już małymi literami (zamieniamy je przy wczytaniu).
f_wy.write(linia) — piszemy oryginalną linię z \n na końcu. Nie robimy strip() bo chcemy zachować oryginalny format.
os.path.exists() sprawdza istnienie pliku przed próbą otwarcia. Lepiej sprawdzić wcześniej niż łapać wyjątek.
Utwórz najpierw przykładowe pliki tekstowe lub CSV — możesz je wygenerować kodem albo wpisać ręcznie w edytorze.
Notatnik
Napisz program który wczytuje linie od użytkownika i zapisuje je do pliku. Wpisanie pustej linii kończy wpisywanie. Wypisz ile linii zapisano.
while True, if not linia: break, tryb 'w'Statystyki pliku
Wczytaj dowolny plik tekstowy. Wypisz: liczbę linii, liczbę słów, liczbę znaków (ze spacjami i bez), najdłuższą linię.
splitlines(), split(), max(..., key=len)Generator CSV
Napisz program generujący plik CSV z losowymi danymi 20 uczniów: imię, klasa (3A/3B/3C), wynik (0–100). Następnie odczytaj go i wypisz statystyki dla każdej klasy.
random.choice(), csv.writer, grupowanie po klasieNumerowanie linii
Wczytaj plik tekstowy i zapisz jego kopię gdzie każda linia ma numer na początku (jak w edytorze kodu): 1 | treść linii.
enumerate(f, 1), f"{i:3} | {linia}"Scalanie plików
Masz kilka plików tekstowych (np. czesc1.txt, czesc2.txt, czesc3.txt). Scal je w jeden plik wynikowy — każdy poprzedzony nagłówkiem z nazwą pliku źródłowego.
'a' lub jeden 'w'Prosta baza danych w CSV
Zaimplementuj CRUD dla pliku CSV z uczniami: dodaj rekord, usuń po imieniu, edytuj wynik, wylistuj wszystkich. Każda operacja zapisuje zmiany do pliku.