Szybki quiz – przypomnienie poprzedniej lekcji
Temat poprzedniej lekcji: operacje na ciągach znaków i wyrażenia regularne.
1. Co zostanie wyświetlone?
tekst = "Python"
print(tekst[1:4], tekst[-2:], tekst[::-1])
Odpowiedź
Odpowiedź: yth on nohtyP – [1:4] to znaki o indeksach 1, 2, 3; [-2:] to dwa ostatnie znaki; [::-1] odwraca napis.
2. Znajdź błąd w kodzie i popraw go.
imie = "ala"
imie[0] = "A"
Odpowiedź
Odpowiedź: TypeError – stringi są niemutowalne, nie można zmienić pojedynczego znaku. Poprawnie: imie = "A" + imie[1:] albo imie = imie.capitalize().
3. Co zostanie wyświetlone?
tekst = "kot"
tekst.replace("k", "m")
print(tekst)
Odpowiedź
Odpowiedź: kot – replace() nie zmienia oryginału, zwraca nowy string. Wynik trzeba przypisać: tekst = tekst.replace("k", "m").
4. Jaki będzie wynik działania programu?
tekst = " Ala ma kota "
print(tekst.strip().upper().split())
Odpowiedź
Odpowiedź: ['ALA', 'MA', 'KOTA'] – strip() usuwa spacje z brzegów, upper() zamienia na wielkie litery, split() dzieli po białych znakach i zwraca listę.
5. Czym różni się find() od index() przy szukaniu tekstu, którego nie ma w napisie?
Odpowiedź
Odpowiedź: find() zwraca -1, a index() zgłasza błąd ValueError.
6. Co należy uzupełnić w kodzie, aby liczba 5 została wyświetlona jako 005?
n = 5
print(f"{n:___}")
Odpowiedź
Odpowiedź: 03d (może być też 03) – wynik 005. Alternatywa bez f-stringa: str(n).zfill(3).
7. Co zwróci ten fragment kodu?
import re
print(re.findall(r"\d+", "Mam 3 koty i 12 psów"))
Odpowiedź
Odpowiedź: ['3', '12'] – \d+ to jedna lub więcej cyfr z rzędu, findall() zwraca listę wszystkich dopasowań.
8. Jak zamienić listę ["a", "b", "c"] na napis a, b, c?
Odpowiedź
Odpowiedź: ", ".join(["a", "b", "c"]) – join() wywołujemy na separatorze, a nie na liście.
Praca z plikami to fundamentalna umiejętność w programowaniu. Pozwala na:
- Zapisywanie danych na stałe (przetrwają zamknięcie programu)
- Wczytywanie danych z plików tekstowych, CSV, JSON
- Tworzenie logów i raportów
- Wymianę danych między programami
Podstawowe operacje:
- Otwieranie pliku
- Odczyt lub zapis danych
- Zamykanie pliku (automatyczne z
with)
Ścieżki do plików
Ścieżka względna vs bezwzględna
Ścieżka względna – relatywna do bieżącego katalogu:
"plik.txt"
"dane/plik.txt"
"../plik.txt"
Ścieżka bezwzględna – pełna ścieżka od korzenia dysku:
# Windows
"C:/Users/Jan/Documents/plik.txt"
# Linux/Mac
"/home/jan/documents/plik.txt"
Moduł os – praca ze ścieżkami
import os
# Bieżący katalog (current working directory)
sciezka_biezaca = os.getcwd()
print(f"Obecny katalog: {sciezka_biezaca}")
# Np. C:\Users\Jan\Python\projekt
# Lista plików i katalogów w bieżącym katalogu
pliki = os.listdir()
print(f"Pliki w katalogu: {pliki}")
# Lista plików w konkretnym katalogu
pliki_dane = os.listdir("dane")
print(pliki_dane)
# Katalog nadrzędny (parent directory)
pliki_nadrzedne = os.listdir('..')
print(f"Pliki w katalogu nadrzędnym: {pliki_nadrzedne}")
Katalog domowy użytkownika
import os
# Katalog domowy
katalog_domowy = os.path.expanduser('~')
print(f"Katalog domowy: {katalog_domowy}")
# Windows: C:\Users\Jan
# Linux: /home/jan
# Mac: /Users/jan
Sprawdzanie istnienia pliku
import os
plik = "dane.txt"
# Czy plik istnieje?
if os.path.exists(plik):
print(f"Plik {plik} istnieje")
else:
print(f"Plik {plik} nie istnieje")
# Czy to plik?
if os.path.isfile(plik):
print("To jest plik")
# Czy to katalog?
if os.path.isdir("dane"):
print("To jest katalog")
Tryby otwierania plików
Przy otwieraniu pliku określamy tryb dostępu:
| Tryb | Nazwa | Opis |
|---|---|---|
'r' | read | Odczyt – plik musi istnieć |
'w' | write | Zapis – tworzy nowy lub nadpisuje istniejący |
'a' | append | Dopisywanie – na końcu pliku, tworzy jeśli nie istnieje |
'x' | exclusive | Tworzenie – błąd jeśli plik istnieje |
'r+' | read/write | Odczyt i zapis – plik musi istnieć |
'w+' | write/read | Zapis i odczyt – nadpisuje |
'a+' | append/read | Dopisywanie i odczyt |
Dodatkowe modyfikatory:
't'– tryb tekstowy (domyślny)'b'– tryb binarny (dla obrazów, audio itp.)
Przykłady:
'r' # Tylko odczyt, tekstowy
'rb' # Tylko odczyt, binarny
'w' # Tylko zapis, tekstowy
'wb' # Tylko zapis, binarny
'a' # Dopisywanie, tekstowy
'r+' # Odczyt i zapis
Instrukcja with – bezpieczne otwieranie
Dlaczego with?
- Automatycznie zamyka plik
- Zwalnia zasoby
Składnia:
with open('plik.txt', 'r') as plik:
# operacje na pliku
zawartosc = plik.read()
# Tutaj plik jest już automatycznie zamknięty
Bez with (NIE ZALECANE)
# Stary sposób - musisz pamiętać o zamknięciu
plik = open('dane.txt', 'r')
zawartosc = plik.read()
plik.close() # Łatwo zapomnieć!
# Problem: jeśli wystąpi błąd, plik może nie zostać zamknięty
Odczyt z pliku
read() – cała zawartość
# Odczyt całego pliku jako jeden string
with open('plik.txt', 'r', encoding='utf-8') as plik:
zawartosc = plik.read()
print(zawartosc)
Parametr encoding='utf-8' – ważny dla polskich znaków!
read(n) – n znaków
# Odczyt pierwszych 100 znaków
with open('plik.txt', 'r', encoding='utf-8') as plik:
fragment = plik.read(100)
print(fragment)
readline() – jedna linia
# Odczyt pojedynczej linii
with open('plik.txt', 'r', encoding='utf-8') as plik:
pierwsza_linia = plik.readline()
druga_linia = plik.readline()
print(pierwsza_linia)
print(druga_linia)
readlines() – lista linii
# Odczyt wszystkich linii jako lista
with open('plik.txt', 'r', encoding='utf-8') as plik:
linie = plik.readlines()
print(type(linie)) # <class 'list'>
print(len(linie)) # Liczba linii
# Iteracja po liniach
for linia in linie:
print(linia.rstrip()) # rstrip() usuwa \n na końcu
Iteracja bezpośrednia (NAJLEPSZE)
# Najbardziej efektywny sposób - bez wczytywania całości do pamięci
with open('plik.txt', 'r', encoding='utf-8') as plik:
for linia in plik:
print(linia.rstrip())
Zalety:
- Oszczędza pamięć (nie wczytuje całego pliku)
- Szybsze dla dużych plików
- Prostsze
Przykład – wyszukiwanie w pliku
# Szukanie linii zawierającej konkretny tekst
with open('log.txt', 'r', encoding='utf-8') as plik:
for numer, linia in enumerate(plik, 1):
if 'ERROR' in linia:
print(f"Linia {numer}: {linia.rstrip()}")
Zapis do pliku
write() – zapis stringa
UWAGA: Tryb 'w' nadpisuje cały plik!
# Zapis do nowego pliku (lub nadpisanie istniejącego)
with open('nowy.txt', 'w', encoding='utf-8') as plik:
plik.write("To jest pierwsza linia\n")
plik.write("To jest druga linia\n")
Ważne: write() NIE DODAJE automatycznie nowej linii – musisz sam dodać \n!
Zapis wielu linii
# Metoda 1: write() z \n
with open('dane.txt', 'w', encoding='utf-8') as plik:
plik.write("Linia 1\n")
plik.write("Linia 2\n")
plik.write("Linia 3\n")
# Metoda 2: writelines() - lista stringów
linie = ["Linia 1\n", "Linia 2\n", "Linia 3\n"]
with open('dane.txt', 'w', encoding='utf-8') as plik:
plik.writelines(linie)
Przykład – zapis listy
# Zapisywanie listy zakupów
zakupy = ["Mleko", "Chleb", "Masło", "Jajka"]
with open('zakupy.txt', 'w', encoding='utf-8') as plik:
for produkt in zakupy:
plik.write(produkt + "\n")
Dopisywanie do pliku (append)
Tryb 'a' dopisuje na końcu pliku, nie nadpisując go.
import datetime
# Dopisywanie z datą i czasem
with open('log.txt', 'a', encoding='utf-8') as plik:
teraz = datetime.datetime.now()
plik.write(f"Log z dnia {teraz}\n")
# Kolejne wywołanie dopisze kolejną linię
with open('log.txt', 'a', encoding='utf-8') as plik:
plik.write("Nowy wpis w logu\n")
Przykład – dziennik
import datetime
def dodaj_wpis(tekst):
"""Dodaje wpis do dziennika z datą."""
with open('dziennik.txt', 'a', encoding='utf-8') as plik:
teraz = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
plik.write(f"[{teraz}] {tekst}\n")
# Użycie
dodaj_wpis("Program uruchomiony")
dodaj_wpis("Użytkownik zalogowany")
dodaj_wpis("Program zamknięty")
Wskaźnik pozycji w pliku
tell() – aktualna pozycja
with open('plik.txt', 'r', encoding='utf-8') as plik:
print(f"Pozycja: {plik.tell()}") # 0
plik.read(10)
print(f"Pozycja: {plik.tell()}") # 10
seek() – przesunięcie wskaźnika
with open('plik.txt', 'r', encoding='utf-8') as plik:
# Przesuń na początek
plik.seek(0)
# Odczyt
dane1 = plik.read(20)
# Wróć na początek
plik.seek(0)
# Odczyt od początku znowu
dane2 = plik.read(20)
Przykład – wielokrotny odczyt
with open('plik.txt', 'r', encoding='utf-8') as plik:
# Pierwszy odczyt
zawartosc1 = plik.read()
print(f"Pierwszy: {len(zawartosc1)} znaków")
# Drugi odczyt (pusty - wskaźnik na końcu)
zawartosc2 = plik.read()
print(f"Drugi: {len(zawartosc2)} znaków") # 0
# Powrót na początek
plik.seek(0)
# Trzeci odczyt (działa)
zawartosc3 = plik.read()
print(f"Trzeci: {len(zawartosc3)} znaków")
Praca z wieloma plikami
Kopiowanie pliku
# Kopiowanie zawartości z jednego pliku do drugiego
with open('zrodlo.txt', 'r', encoding='utf-8') as zrodlo, \
open('kopia.txt', 'w', encoding='utf-8') as cel:
zawartosc = zrodlo.read()
cel.write(zawartosc)
print("Plik skopiowany")
Łączenie plików
# Łączenie wielu plików w jeden
pliki_zrodlowe = ['plik1.txt', 'plik2.txt', 'plik3.txt']
with open('polaczony.txt', 'w', encoding='utf-8') as wyjscie:
for nazwa_pliku in pliki_zrodlowe:
with open(nazwa_pliku, 'r', encoding='utf-8') as wejscie:
zawartosc = wejscie.read()
wyjscie.write(zawartosc)
wyjscie.write("\n" + "="*50 + "\n") # Separator
print("Pliki połączone")
Przetwarzanie i zapisywanie
# Odczyt, przetworzenie, zapis
with open('dane.txt', 'r', encoding='utf-8') as wejscie, \
open('przetworzone.txt', 'w', encoding='utf-8') as wyjscie:
for linia in wejscie:
# Przetwarzanie - wielkie litery
przetworzona = linia.upper()
wyjscie.write(przetworzona)
Obsługa błędów
try-except dla plików
try:
with open('nieistniejacy.txt', 'r', encoding='utf-8') as plik:
zawartosc = plik.read()
except FileNotFoundError:
print("Błąd: Plik nie istnieje!")
except PermissionError:
print("Błąd: Brak uprawnień do pliku!")
except Exception as e:
print(f"Nieoczekiwany błąd: {e}")
Sprawdzanie przed otwarciem
import os
nazwa_pliku = 'dane.txt'
# Sprawdź czy istnieje
if os.path.exists(nazwa_pliku):
with open(nazwa_pliku, 'r', encoding='utf-8') as plik:
zawartosc = plik.read()
print(zawartosc)
else:
print(f"Plik {nazwa_pliku} nie istnieje")
Pliki binarne
Odczyt pliku binarnego
# Odczyt obrazu
with open('obrazek.jpg', 'rb') as plik: # 'rb' - read binary
dane_binarne = plik.read()
print(f"Rozmiar: {len(dane_binarne)} bajtów")
Kopiowanie pliku binarnego
# Kopiowanie obrazu
with open('zdjecie.jpg', 'rb') as zrodlo, \
open('kopia_zdjecia.jpg', 'wb') as cel:
dane = zrodlo.read()
cel.write(dane)
print("Obraz skopiowany")
Przykłady praktyczne
Przykład 1: System logowania
import datetime
def zapisz_log(wiadomosc, poziom="INFO"):
"""Zapisuje log z datą i poziomem."""
with open('aplikacja.log', 'a', encoding='utf-8') as plik:
teraz = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
plik.write(f"[{teraz}] [{poziom}] {wiadomosc}\n")
# Użycie
zapisz_log("Aplikacja uruchomiona")
zapisz_log("Użytkownik Jan zalogowany")
zapisz_log("Błąd połączenia z bazą danych", "ERROR")
zapisz_log("Aplikacja zamknięta")
Przykład 2: Książka adresowa
def dodaj_kontakt(imie, telefon):
"""Dodaje kontakt do pliku."""
with open('kontakty.txt', 'a', encoding='utf-8') as plik:
plik.write(f"{imie}|{telefon}\n")
print(f"Kontakt {imie} dodany")
def wyswietl_kontakty():
"""Wyświetla wszystkie kontakty."""
try:
with open('kontakty.txt', 'r', encoding='utf-8') as plik:
print("\n=== KONTAKTY ===")
for linia in plik:
imie, telefon = linia.strip().split('|')
print(f"{imie}: {telefon}")
except FileNotFoundError:
print("Brak kontaktów")
def znajdz_kontakt(szukane_imie):
"""Znajduje kontakt po imieniu."""
try:
with open('kontakty.txt', 'r', encoding='utf-8') as plik:
for linia in plik:
imie, telefon = linia.strip().split('|')
if imie.lower() == szukane_imie.lower():
print(f"Znaleziono: {imie} - {telefon}")
return
print("Kontakt nie znaleziony")
except FileNotFoundError:
print("Brak pliku kontaktów")
# Użycie
dodaj_kontakt("Jan Kowalski", "123-456-789")
dodaj_kontakt("Anna Nowak", "987-654-321")
wyswietl_kontakty()
znajdz_kontakt("Jan Kowalski")
Przykład 3: Statystyki tekstu
def statystyki_pliku(nazwa_pliku):
"""Wyświetla statystyki pliku tekstowego."""
try:
with open(nazwa_pliku, 'r', encoding='utf-8') as plik:
linie = plik.readlines()
liczba_linii = len(linie)
liczba_slow = 0
liczba_znakow = 0
for linia in linie:
liczba_znakow += len(linia)
liczba_slow += len(linia.split())
print(f"=== STATYSTYKI: {nazwa_pliku} ===")
print(f"Liczba linii: {liczba_linii}")
print(f"Liczba słów: {liczba_slow}")
print(f"Liczba znaków: {liczba_znakow}")
print(f"Średnia długość linii: {liczba_znakow / liczba_linii:.2f}")
except FileNotFoundError:
print(f"Plik {nazwa_pliku} nie istnieje")
# Użycie
statystyki_pliku('tekst.txt')
Przykład 4: Filtrowanie pliku
def filtruj_plik(plik_wejsciowy, plik_wyjsciowy, slowo_kluczowe):
"""
Kopiuje tylko linie zawierające słowo kluczowe.
"""
licznik = 0
with open(plik_wejsciowy, 'r', encoding='utf-8') as wejscie, \
open(plik_wyjsciowy, 'w', encoding='utf-8') as wyjscie:
for linia in wejscie:
if slowo_kluczowe.lower() in linia.lower():
wyjscie.write(linia)
licznik += 1
print(f"Skopiowano {licznik} linii zawierających '{slowo_kluczowe}'")
# Użycie
filtruj_plik('log.txt', 'bledy.txt', 'ERROR')
Przykład 5: Licznik wyrazów
from collections import Counter
def licznik_wyrazow(nazwa_pliku):
"""Zlicza wystąpienia każdego słowa w pliku."""
try:
with open(nazwa_pliku, 'r', encoding='utf-8') as plik:
tekst = plik.read().lower()
# Usuwanie znaków interpunkcyjnych (prosty sposób)
import string
for znak in string.punctuation:
tekst = tekst.replace(znak, ' ')
# Podział na słowa
slowa = tekst.split()
# Zliczanie
licznik = Counter(slowa)
# Wyświetlanie 10 najczęstszych
print(f"\n10 najczęstszych słów w {nazwa_pliku}:")
for slowo, liczba in licznik.most_common(10):
print(f"{slowo}: {liczba}")
except FileNotFoundError:
print(f"Plik {nazwa_pliku} nie istnieje")
# Użycie
licznik_wyrazow('artykul.txt')
CSV – pliki z danymi tabelarycznymi
Zapis do CSV
import csv
# Dane do zapisania
dane = [
['Imię', 'Wiek', 'Miasto'],
['Jan', 25, 'Warszawa'],
['Anna', 30, 'Kraków'],
['Piotr', 28, 'Gdańsk']
]
# Zapis do CSV
with open('osoby.csv', 'w', newline='', encoding='utf-8') as plik:
writer = csv.writer(plik)
writer.writerows(dane)
print("Dane zapisane do CSV")
Odczyt z CSV
import csv
# Odczyt z CSV
with open('osoby.csv', 'r', encoding='utf-8') as plik:
reader = csv.reader(plik)
for wiersz in reader:
print(wiersz)
Ćwiczenia – Operacje na plikach
Podstawy odczytu
- Stwórz plik
test.txtz 3 liniami tekstu. Odczytaj i wyświetl całą zawartość. - Odczytaj tylko pierwsze 50 znaków z pliku.
- Odczytaj pierwszą linię z pliku używając
readline(). - Odczytaj wszystkie linie z pliku używając
readlines()i wyświetl ich liczbę. - Przejdź przez plik linijka po linijce używając pętli
for. - Odczytaj plik i policz ile jest w nim słów.
- Odczytaj plik i policz ile jest w nim znaków (z spacjami).
- Znajdź najdłuższą linię w pliku.
- Wyświetl tylko linie zawierające słowo „Python”.
- Policz ile razy w pliku występuje konkretne słowo.
Podstawy zapisu
- Stwórz nowy plik i zapisz w nim 3 linie tekstu.
- Zapisz listę 5 imion do pliku (każde w nowej linii).
- Zapisz liczby od 1 do 100 do pliku (każda w nowej linii).
- Stwórz plik i zapisz w nim tabliczkę mnożenia dla liczby 7.
- Pobierz od użytkownika 5 zdań i zapisz je do pliku.
Dopisywanie (append)
- Dopisz aktualna datę i czas do pliku logu.
- Stwórz funkcję która dopisuje wpis do dziennika z datą.
- Pobieraj od użytkownika notatki i dopisuj je do pliku dopóki nie wpisze „koniec”.
- Dopisz do istniejącego pliku listę nowych zadań.
- Stwórz prosty system TODO który dopisuje zadania do pliku.
Operacje na wielu plikach
- Skopiuj zawartość jednego pliku do drugiego.
- Połącz dwa pliki tekstowe w jeden.
- Odczytaj plik, zamień wszystkie litery na wielkie i zapisz do nowego pliku.
- Odczytaj plik, usuń puste linie i zapisz do nowego pliku.
- Odczytaj plik, ponumeruj linie i zapisz do nowego pliku.
Przetwarzanie danych
- Odczytaj plik z liczbami (każda w linii) i oblicz ich sumę.
- Odczytaj plik z liczbami i znajdź największą oraz najmniejszą.
- Odczytaj plik tekstowy i stwórz plik ze statystykami (liczba linii, słów, znaków).
- Odczytaj plik i zapisz tylko linie dłuższe niż 50 znaków do nowego pliku.
- Odczytaj plik i zapisz linie w odwrotnej kolejności do nowego pliku.
Filtrowanie i wyszukiwanie
- Znajdź i wyświetl wszystkie linie zawierające „@” (adresy email).
- Skopiuj do nowego pliku tylko linie zaczynające się od „#” (komentarze).
- Odczytaj plik logu i zapisz do nowego tylko linie zawierające „ERROR”.
- Znajdź wszystkie linie zawierające liczby i zapisz je osobno.
- Usuń z pliku wszystkie linie zawierające konkretne słowo.
Praca ze ścieżkami (moduł os)
- Wyświetl bieżący katalog roboczy.
- Wyświetl listę wszystkich plików w bieżącym katalogu.
- Sprawdź czy plik o podanej nazwie istnieje.
- Wyświetl listę wszystkich plików .txt w katalogu.
- Policz ile plików znajduje się w katalogu.
Obsługa błędów
- Spróbuj otworzyć nieistniejący plik i obsłuż błąd.
- Napisz funkcję która bezpiecznie odczytuje plik (obsługuje błędy).
- Sprawdź czy plik istnieje przed próbą otwarcia.
- Obsłuż błąd braku uprawnień do pliku.
- Napisz funkcję która próbuje otworzyć plik 3 razy przed poddaniem się.
Funkcje do pracy z plikami
- Napisz funkcję
zapisz_liste(lista, nazwa_pliku)która zapisuje listę do pliku. - Napisz funkcję
wczytaj_liste(nazwa_pliku)która wczytuje listę z pliku. - Napisz funkcję
policz_linie(nazwa_pliku)która zwraca liczbę linii. - Napisz funkcję
znajdz_w_pliku(nazwa_pliku, szukane)która znajduje i zwraca linie zawierające szukany tekst. - Napisz funkcję
usun_duplikaty(plik_wejsciowy, plik_wyjsciowy)która usuwa powtarzające się linie.
CSV i dane strukturalne
- Zapisz listę słowników do pliku CSV (bez modułu csv).
- Odczytaj plik CSV i wyświetl dane w formacie tabelarycznym.
- Stwórz plik CSV z danymi uczniów (imię, nazwisko, klasa, średnia).
- Odczytaj plik CSV i znajdź ucznia z najwyższą średnią.
- Stwórz plik CSV z cenami produktów. Oblicz wartość całego magazynu.
JSON
- Zapisz słownik do pliku JSON.
- Odczytaj dane z pliku JSON.
- Zapisz listę słowników (dane użytkowników) do pliku JSON.
- Odczytaj JSON, zmodyfikuj dane i zapisz z powrotem.
- Stwórz bazę danych kontaktów w formacie JSON.
Pliki binarne
- Skopiuj plik binarny (np. obrazek).
- Sprawdź rozmiar pliku binarnego w bajtach.
- Odczytaj pierwsze 100 bajtów z pliku binarnego.
- Porównaj rozmiary pliku tekstowego i tego samego pliku skompresowanego.
- Napisz funkcję która sprawdza typ pliku na podstawie rozszerzenia.
Logowanie
- Stwórz prosty system logowania który zapisuje logi z datą i czasem.
- Napisz funkcję
log(wiadomosc, poziom)która loguje z poziomami (INFO, WARNING, ERROR). - Stwórz osobne pliki logów dla różnych poziomów.
- Ogranicz rozmiar pliku logu – jeśli przekroczy 1000 linii, zacznij nowy plik.
- Napisz funkcję która wyświetla ostatnie 10 linii z logu.
Kontakty/Książka adresowa
- Stwórz system dodawania kontaktów do pliku (imię, telefon, email).
- Napisz funkcję wyświetlającą wszystkie kontakty z pliku.
- Napisz funkcję wyszukującą kontakt po imieniu.
- Napisz funkcję usuwającą kontakt.
- Napisz funkcję edytującą kontakt.
TODO list
- Stwórz prosty system TODO z zapisem do pliku.
- Dodaj możliwość oznaczania zadań jako wykonane.
- Dodaj priorytet zadań (niski, średni, wysoki).
- Wyświetl tylko zadania nieukończone.
- Posortuj zadania według priorytetu.
Statystyki i analizy
- Napisz funkcję analizującą plik tekstowy (najczęstsze słowo, najdłuższe słowo, średnia długość słowa).
- Policz wystąpienia każdej litery w pliku.
- Stwórz histogram długości słów w pliku.
- Znajdź wszystkie unikalne słowa w pliku.
- Policz ile razy każde słowo występuje w pliku (użyj Counter).
Backup i archiwizacja
- Napisz funkcję tworzącą kopię zapasową pliku (dopisz datę do nazwy).
- Stwórz funkcję która zapisuje historię zmian w pliku.
- Napisz funkcję która przywraca plik z backupu.
- Stwórz rotację backupów – zachowaj tylko 5 najnowszych.
- Napisz funkcję porównującą dwa pliki i wyświetlającą różnice.
Konfiguracja
- Stwórz plik konfiguracyjny (nazwa=wartość w każdej linii) i funkcje do odczytu.
- Napisz funkcję zapisującą ustawienia do pliku konfiguracyjnego.
- Stwórz domyślną konfigurację jeśli plik nie istnieje.
- Waliduj konfigurację podczas wczytywania.
- Dodaj komentarze do pliku konfiguracyjnego (linie zaczynające się od #).
Raportowanie
- Napisz funkcję generującą raport HTML z danymi z pliku.
- Stwórz raport zawierający statystyki z wielu plików.
- Wygeneruj raport CSV z podsumowaniem danych.
- Stwórz raport tekstowy z formatowaniem (ramki, wyrównanie).
- Napisz funkcję która generuje raport porównawczy z dwóch plików.
Zadania kompleksowe
- Stwórz prosty system zarządzania uczniami: dodawanie, usuwanie, edycja, wyświetlanie, zapisywanie do pliku.
- Napisz program do analizy logów serwera: zlicz błędy, ostrzeżenia, wyświetl statystyki.
- Stwórz system inwentaryzacji: produkty z ilościami, cenami, raport wartości magazynu.
- Napisz program do zarządzania wydatkami: dodawanie wydatków, kategorie, raporty miesięczne, zapis do pliku.
- Stwórz system rezerwacji: terminy, zarezerwowane/wolne, zapis do pliku, walidacja.
- Napisz grę tekstową która zapisuje stan gry do pliku i pozwala wczytać zapisany stan.
- Stwórz prosty system blogowy: posty z datą, tytułem, treścią, zapisywanie do plików.
- Napisz konwerter między formatami (TXT ↔ CSV ↔ JSON).
- Stwórz system punktacji quizu z zapisem wyników do pliku i rankingiem.
- Napisz program szyfrujący i deszyfrujący pliki tekstowe (np. szyfr Cezara).
PODSUMOWANIE
Co uczeń musi rozumieć w tym temacie:
- Plik to trwałe miejsce zapisu danych – po zamknięciu programu dane zostają. Praca z plikiem to zawsze: otwórz → odczytaj/zapisz → zamknij.
- Plik otwieramy przez
with open(...) as plik:. Blokwithgwarantuje zamknięcie pliku, także gdy w środku wystąpi błąd. Nie zastępuje jednaktry/except– błędu, np. braku pliku, nadal trzeba obsłużyć osobno. - Tryb otwarcia decyduje o tym, co się stanie z plikiem:
'r'– odczyt, plik musi istnieć,'w'– zapis, kasuje dotychczasową zawartość (albo tworzy plik),'a'– dopisywanie na końcu,'x'– utworzenie nowego pliku, błąd jeśli już istnieje.
write()zapisuje dokładnie to, co dostanie, i nie dodaje\n. Podział na linie to sprawa programisty.write()przyjmuje tylkostr– liczby trzeba zamienić przezstr()lub f-string.- Odczyt zwraca tekst:
read()– całość,readline()– jedną linię,readlines()– listę linii. Linie z pliku zawierają\nna końcu – dlatego używamyrstrip()lubstrip(). - Najlepszy sposób czytania linia po linii to pętla
for linia in plik:(nie wczytuje całego pliku do pamięci). - Plik ma wskaźnik pozycji. Po odczycie całości wskaźnik jest na końcu i kolejne
read()zwraca''. Powrót na początek:seek(0). - Polskie znaki wymagają
encoding='utf-8'wopen(). Bez niego odczyt może dać błąd lub „krzaczki” (zależy od systemu). - Dla plików binarnych (obrazy, audio) używamy trybów z
b('rb','wb') – dane są wtedy bajtami, a nie tekstem. Parametruencodingw trybie binarnym nie podajemy. - Typowe błędy wykonania przy plikach:
FileNotFoundError(brak pliku),PermissionError(brak uprawnień),FileExistsError(tryb'x'). - Moduł
ospozwala sprawdzić środowisko przed otwarciem pliku:os.getcwd(),os.listdir(),os.path.exists(),os.path.isfile(),os.path.isdir(). - Dane tabelaryczne zapisujemy i czytamy modułem
csv(csv.writer,csv.reader). Przy zapisie dodajemynewline=''.
Najczęstsze źródła błędów:
- użycie
'w'zamiast'a'i utrata starych danych, - brak
\nwwrite()– wszystko ląduje w jednej linii, write()z liczbą zamiast napisu,- próba odczytu po wyjściu z bloku
with(plik jest już zamknięty), - ponowny
read()bezseek(0)– pusty wynik, - zapomniane
rstrip()– puste linie w wydruku, boprint()też dodaje\n, - zła ścieżka lub zły katalog roboczy (plik istnieje, ale nie w miejscu, gdzie szuka go program),
- brak
encoding='utf-8'.
Minimum, które powinno wejść w pamięć
Jeżeli masz zapamiętać tylko kilka rzeczy z tej lekcji, zapamiętaj te:
- Plik zawsze otwieraj tak:
with open('plik.txt', 'r', encoding='utf-8') as plik: - Tryby:
rodczyt,wzapis (kasuje stare dane!),adopisywanie,xtylko nowy plik. write()nie dodaje\n– dodaj go sam i zapisuj tylko napisy (str).- Linie z pliku mają
\nna końcu – usuń go przezrstrip()/strip(). - Czytanie linia po linii:
for linia in plik: - Po przeczytaniu całego pliku wskaźnik jest na końcu – wróć na początek przez
seek(0). - Brak pliku to
FileNotFoundError– obsłuż go przeztry/except. - Zanim użyjesz pliku, możesz sprawdzić
os.path.exists(nazwa). - Dane w jednej linii rozdzielone znakiem (np.
Jan|123) czytasz przezstrip().split('|')– to połączenie tej lekcji z poprzednią. - Obrazy i inne pliki nietekstowe: tryby
'rb'i'wb'.
Ściągawka – najważniejsze polecenia i składnia
Otwieranie pliku
with open('plik.txt', 'r', encoding='utf-8') as plik:
... # tutaj plik jest otwarty; po wyjściu z bloku – zamknięty
Tryby
| Tryb | Znaczenie | Gdy brak pliku | Gdy plik istnieje |
|---|---|---|---|
'r' | odczyt | FileNotFoundError | czyta |
'w' | zapis | tworzy | kasuje zawartość |
'a' | dopisywanie | tworzy | dopisuje na końcu |
'x' | tworzenie | tworzy | FileExistsError |
'r+' | odczyt i zapis | FileNotFoundError | czyta i zapisuje |
'rb', 'wb' | binarnie | jak 'r', 'w' | jak 'r', 'w' |
Odczyt
| Instrukcja | Zwraca |
|---|---|
plik.read() | cały plik jako jeden string |
plik.read(n) | n znaków |
plik.readline() | jedną linię (z \n) |
plik.readlines() | listę linii (z \n) |
for linia in plik: | kolejne linie, bez wczytywania całości |
Zapis
plik.write("tekst\n") # jeden napis, \n dodajemy sami
plik.writelines(["a\n", "b\n"]) # lista napisów, każdy z \n
plik.write(str(liczba) + "\n") # liczbę najpierw na string
Wskaźnik pozycji
plik.tell() # aktualna pozycja
plik.seek(0) # skok na początek
Dwa pliki naraz
with open('we.txt', 'r', encoding='utf-8') as we, \
open('wy.txt', 'w', encoding='utf-8') as wy:
for linia in we:
wy.write(linia.upper())
Obsługa błędów
try:
with open('dane.txt', 'r', encoding='utf-8') as plik:
...
except FileNotFoundError:
print("Plik nie istnieje")
except PermissionError:
print("Brak uprawnień")
Moduł os
import os
os.getcwd() # bieżący katalog
os.listdir() # lista plików i katalogów
os.path.exists('x.txt') # czy istnieje (plik lub katalog)
os.path.isfile('x.txt') # czy to plik
os.path.isdir('dane') # czy to katalog
CSV
import csv
with open('osoby.csv', 'w', newline='', encoding='utf-8') as plik:
csv.writer(plik).writerows(dane) # dane = lista list
with open('osoby.csv', 'r', encoding='utf-8') as plik:
for wiersz in csv.reader(plik): # wiersz = lista
print(wiersz)
Wzorzec: dopisywanie wpisu z datą
import datetime
with open('log.txt', 'a', encoding='utf-8') as plik:
teraz = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
plik.write(f"[{teraz}] {tekst}\n")
Quiz – sprawdź się
1. (Teoria) Przypisz do każdego opisu tryb: 'r', 'w', 'a', 'x'.
- a) Dopisuje dane na końcu pliku, a gdy pliku nie ma – tworzy go.
- b) Zgłasza błąd, jeśli plik już istnieje.
- c) Kasuje dotychczasową zawartość pliku.
- d) Wymaga, aby plik istniał.
2. (Teoria) Podaj dwie korzyści używania with open(...) zamiast open() i close().
3. (Co zostanie zapisane?) Jaka będzie zawartość pliku a.txt po uruchomieniu kodu? Ile będzie w nim linii?
with open("a.txt", "w", encoding="utf-8") as p:
p.write("Ala")
p.write("Ola\n")
p.write("Ela")
4. (Co zostanie wyświetlone?) Plik dane.txt zawiera trzy linie: Ala, Ma, Kota.
with open("dane.txt", "r", encoding="utf-8") as p:
p.readline()
print(p.read().split())
5. (Znajdź błąd) Program ma zapisać do pliku liczbę punktów. Dlaczego się nie uruchomi i jak go poprawić?
punkty = 100
with open("wyniki.txt", "w", encoding="utf-8") as p:
p.write(punkty)
6. (Znajdź błąd) Co się stanie po uruchomieniu i dlaczego?
with open("dane.txt", "r", encoding="utf-8") as p:
pierwsza = p.readline()
druga = p.readline()
7. (Uzupełnij kod) Dopisz do pliku log.txt nową linię o treści Start, nie kasując poprzednich wpisów. Co wstawić w miejsca ___?
with open("log.txt", "___", encoding="utf-8") as p:
p.write("Start___")
8. (Przewidywanie działania) Plik litery.txt zawiera jedną linię: abcdef. Co zostanie wyświetlone?
with open("litery.txt", "r", encoding="utf-8") as p:
a = p.read(2)
b = p.read(2)
p.seek(0)
c = p.read(3)
print(a, b, c)
9. (Dlaczego tak działa?) Po wypisaniu zawartości pliku pętlą między liniami pojawiają się puste wiersze. Dlaczego? Jak to naprawić?
with open("lista.txt", "r", encoding="utf-8") as p:
for linia in p:
print(linia)
10. (Co zostanie wyświetlone?) Plik brak.txt nie istnieje.
try:
with open("brak.txt", "r", encoding="utf-8") as p:
print(p.read())
except FileNotFoundError:
print("Brak pliku")
print("Koniec")
11. (Połączenie z poprzednią lekcją) Linia z pliku kontakty.txt ma postać "Jan|123\n". Co zwróci wyrażenie "Jan|123\n".strip().split("|")? Jak użyć go do przypisania imienia i telefonu do dwóch zmiennych?
12. (Wybór poprawnej składni) Która wersja poprawnie otwiera plik CSV do zapisu?
- A)
open('osoby.csv', 'r', newline='', encoding='utf-8') - B)
open('osoby.csv', 'w', newline='', encoding='utf-8') - C)
open('osoby.csv', 'a+b', encoding='utf-8')
13. (Zadanie praktyczne) Napisz program, który zapisuje do pliku liczby.txt liczby od 1 do 5, każdą w osobnej linii.
14. (Zadanie praktyczne) Napisz funkcję suma_z_pliku(nazwa_pliku), która odczytuje plik z liczbami całkowitymi (jedna w linii) i zwraca ich sumę. Jeśli pliku nie ma, funkcja ma wypisać komunikat i zwrócić 0.
Odpowiedzi
1. a) 'a', b) 'x', c) 'w', d) 'r'.
2. Np.: plik jest zamykany automatycznie, także wtedy, gdy w bloku wystąpi błąd; nie trzeba pamiętać o close(); kod jest krótszy i czytelniejszy.
3. Zawartość: AlaOla w pierwszej linii i Ela w drugiej (AlaOla\nEla). Są 2 linie – pierwszy write() nie ma \n, więc „Ala” i „Ola” są połączone.
4. ['Ma', 'Kota'] – readline() pobiera i pomija pierwszą linię, read() zwraca resztę, split() dzieli ją na słowa.
5. TypeError – write() przyjmuje tylko napis. Poprawnie: p.write(str(punkty) + "\n") albo p.write(f"{punkty}\n").
6. ValueError (operacja na zamkniętym pliku). Po wyjściu z bloku with plik jest zamknięty – drugi readline() trzeba wykonać wewnątrz bloku (z wcięciem).
7. Tryb "a" oraz \n: open("log.txt", "a", ...) i p.write("Start\n").
8. ab cd abc – dwa odczyty po 2 znaki dają ab i cd, seek(0) wraca na początek, więc trzeci odczyt daje abc.
9. Każda linia z pliku kończy się znakiem \n, a print() dodaje kolejny – stąd puste wiersze. Poprawka: print(linia.rstrip()) (lub strip()).
10. Wyświetli się:
Brak pliku
Koniec
Błąd został obsłużony, więc program nie przerywa działania i wykonuje ostatnią linię.
11. Wynik: ['Jan', '123']. Przypisanie: imie, telefon = "Jan|123\n".strip().split("|"). Gdyby nie strip(), telefon zawierałby \n na końcu.
12. B – tryb 'w' służy do zapisu; A otwiera plik tylko do odczytu, a C to tryb binarny, nieodpowiedni dla pliku CSV.
13. Przykładowe rozwiązanie:
with open("liczby.txt", "w", encoding="utf-8") as plik:
for i in range(1, 6):
plik.write(f"{i}\n")
14. Przykładowe rozwiązanie:
def suma_z_pliku(nazwa_pliku):
suma = 0
try:
with open(nazwa_pliku, "r", encoding="utf-8") as plik:
for linia in plik:
suma += int(linia.strip())
except FileNotFoundError:
print(f"Plik {nazwa_pliku} nie istnieje")
return 0
return suma