Przejdź do treści
Strona główna » Blog » Kurs Python: operacje na plikach

Kurs Python: operacje na plikach

Operacje na plikach są wykorzystywane w wielu zagadnieniach programistycznych. Jednym z takich zagadnień może być masowa obróbka plików graficznych (np. zmiana rozmiaru, kolorów), filtrowanie plików o wybranych rozszerzeniach i wiele innych. Język Python dysponuje sporym zbiorem funkcji wbudowanych do operacji na plikach. Funkcjonalność języka w tym obszarze możemy poszerzyć wykorzystując bardziej specjalistyczne biblioteki. Poniżej omówię podstawy obsługi plików, czyli takie zadania jak odczyt, zapis czy kopiowanie.

Otwieranie pliku

Przed wykonaniem jakichkolwiek działań na pliku, musimy go najpierw otworzyć. Zrobimy to przy użyciu funkcji open(). Posłużymy się przykładowym plikiem tekstowym plik1.txt o treści:

To jest przykladowy plik tekstowy.
Do zobaczenia!

Plik otwieramy przy użyciu instrukcji:

Python
plik1 = open("plik1.txt")

Pliki możemy otwierać w różnych trybach. Domyślnie plik jest otwierany w trybie tylko do odczytu. Do wskazania, który tryb chcemy wykorzystać, używamy dodatkowego argumentu, jak w poniższych przykładach:

  1. Tryb odczytu ('r'): Pozwala na odczytanie zawartości istniejącego pliku. Jeśli plik nie istnieje, wystąpi błąd.
Python
file = open('plik1.txt', 'r')
  1. Tryb zapisu ('w'): Tworzy nowy plik do zapisu danych. Jeśli plik już istnieje, nadpisuje go nową zawartością.
Python
file = open('plik1.txt', 'w')
  1. Tryb dopisywania ('a'): Otwiera plik do dopisywania danych na końcu istniejącej zawartości. Jeśli plik nie istnieje, tworzy nowy.
Python
file = open('plik1.txt', 'a')

Odczyt z pliku

Po otwarciu pliku możemy wczytać jego treść do jednej zmiennej za pomocą funkcji read():

Python
# otwórz plik
plik = open("plik1.txt")

# wczytaj plik
read_content = plik.read()

print(read_content)

Wynik:

To jest przykladowy plik tekstowy.
Do zobaczenia!

Zapis do pliku

Aby zapisać treść do pliku musimy otworzyć z parametrem w. Do zapisu wykorzystujemy funkcję write().

Python
# otwórz plik2.txt w trybie do zapisu

plik2 = open('plik2.txt', 'w')

# zapisz treść do plik2.txt
plik2.write('Zapisana tresc do pliku.\n')
plik2.write('Koniec pliku.\n')
plik2.close()

Zwróćmy uwagę, że każda linia zapisywana do pliku zakończona jest znakiem końca linii, czyli \n. Gdybśmy pominęli ten znak, to funkcja write() dopisałaby ciąg znaków w tej samej linii, a plik po modyfikacji wyglądałby tak:

Zapisana tresc do pliku.Koniec pliku.

Kolejną kwestią jest konieczność zamknięcia pliku przy użyciu funkcji close(), co jest konieczne, aby program wprowadził w nim zmiany. Jeżeli tego nie zrobimy, to możemy mieć również problemy z dostępem do pliku przez inne programy.

Zapis do pliku przy użyciu with open

Możemy wykorzystać inny specjalny zapis, który automatycznie powoduje zamknięcie pliku.

Python
# Dane do dopisania
nowe_dane = "Nowe dane, ktore zostana dopisane do pliku."

# Otwarcie pliku w trybie dopisywania ('a' - append)
with open('plik_do_zapisu.txt', 'w') as file:
    # Dopisanie nowych danych do pliku
    file.write("\n")  # Dodanie nowej linii przed nowymi danymi
    file.write(nowe_dane)

print("Nowe dane zostaly dopisane do pliku.")

Widzimy, że stworzyliśmy cały blok with, który jest odpowiedzialny za operacje na pliku, po których zakończeniu zostanie on zamknięty.

Korzystanie z trybu dopisywania

Tryb ten służy do dołączania treści do istniejącego już pliku. W tym ćwiczeniu wykorzystamy wcześniej stworzony plik plik1.txt, do którego dodamy nową linijkę tekstu.

Python
# Przykład zastosowania trybu append()
plik = open('plik1.txt', 'a')
plik.write("\n")  # Dodanie nowej linii przed nowymi danymi
plik.write("To jest nowa linia")
plik.close()

Po uruchomieniu programu, plik1.txt będzie wyglądał następująco:

To jest przykladowy plik tekstowy.
Do zobaczenia!
To jest nowa linia

Zwróćmy uwagę, że użycie trybu zapisu 'w' spowodowałoby nadpisanie całej zawartości pliku.

Zapis polskich znaków do pliku tekstowego


We wcześniejszych przykładach nie stosowaliśmy polskich znaków. Użycie ich wywołałoby błąd UnicodeEncodeError. Związane jest to z próbą zapisu znaków, które nie są obsługiwane w standardzie kodowania cp1252, który jest domyślnym kodowaniem w niektórych systemach Windows. Rozwiązaniem tego problemu jest ustawienie kodowania na utf-8, które pozwoli na zapisywanie znaków Unicode.

Python
plik2 = open('plik2.txt', 'w', encoding='utf-8')

# zapisz treść do plik2.txt
plik2.write('Zapisana treść do pliku.\n')
plik2.write('Koniec pliku.\n')
plik2.close()

Wbudowane funkcje Python do odczytu i zapisu

Oprócz wyżej wymienionych funkcji Python dostarcza jeszcze kilka wbudowanych funkcji służących do odczytu i zapisu w plikach. Poniżej przedstawiłem kilka przykładowych:

  • readline(): odczytuje linię z pliku i zwraca jako ciąg znaków.
  • readlines(): zwraca listę, w której każdy element jest pojedynczą linią pliku.
  • writelines(): zapisuje listę ciągów znaków do pliku.
  • append(): dołącza ciąg znaków do pliku zamiast nadpisywać plik.
  • seek(): przesuwa wskaźnik pozycji w pliku na określoną pozycję.

Kopiowanie pliku w Pythonie przy użyciu modułu shutil

Do kopiowania plików w Pythonie możemy użyć modułu shutil, a konkretnie funkcję copyfiles():

Python
import shutil

# Ścieżka pliku źródłowego i docelowego
plik_zrodlowy = 'e:\Folder_1\plik.txt'
plik_docelowy = 'e:\Folder_2\plik.txt'

# Skopiowanie pliku z plik_zrodlowy.txt do plik_docelowy.txt
shutil.copyfile(plik_zrodlowy, plik_docelowy)

print("Plik został skopiowany.")

Funkcja copyfile() kopiuje zawartość pliku źródłowego do pliku docelowego. Jeśli plik docelowy już istnieje, zostanie on nadpisany.

Usuwanie pliku w Pythonie przy użyciu modułu os

Do usuwania plików w Pythonie służy funkcja os.remove() z modułu os.

Python
import os

# Ścieżka do pliku, który chcemy usunąć
sciezka_do_pliku = 'e:\Folder_2\plik.txt'

# Sprawdzenie, czy plik istnieje
if os.path.exists(sciezka_do_pliku):
    # Usunięcie pliku
    os.remove(sciezka_do_pliku)
    print(f"Plik {sciezka_do_pliku} został usunięty.")
else:
    print(f"Plik {sciezka_do_pliku} nie istnieje.")

W powyższym przykładzie widzimy, że zanim usuniemy plik (linia 9), to sprawdzamy czy ten plik istnieje przy użyciu funkcji os.path.exists(). Wynika to z faktu, że gdybyśmy chcieli usunąć nieistniejący plik, to program zwróciłby błąd:

Alternatywnym podejściem jest obsługa wyjątków, która opisana zostanie bardziej obszernie w innym artykule. W tym rozwiązaniu fragment kodu, który może wywołać FileNotFoundError umieszczamy w bloku try. W przypadku wystąpienia tego błędu zostanie on przechwycony przez instrukcję except. Kod programu wygląda następująco:

Python
import os

sciezka_do_pliku = 'plik_do_usuniecia.txt'

try:
    os.remove(sciezka_do_pliku)
    print(f"Plik {sciezka_do_pliku} został usunięty.")
except FileNotFoundError as e:
    print(f"Błąd podczas usuwania pliku {sciezka_do_pliku}: {e}")

Pliki csv

CSV (ang. comma-separated values) to popularny format pliku tekstowego, w którym dane odzwierciedlają zapis tabelaryczny. Każda linia w pliku csv reprezentuje wiersz tabeli, a wartości oddzielane przecinkiem, bądź innym zdefiniowanym znakiem, odpowiadają poszczególnym komórkom tabeli. Weźmy przykładowy plik kontakty.csv, o następującej treści:

Imię,Nazwisko,Email,Telefon
Jan,Kowalski,[email protected],123456789
Anna,Nowak,[email protected],987654321

Plik ten w formie tabelarycznej (np. w Excelu) wyglądałby następująco:

ImięNazwiskoEmailTelefon
JanKowalski[email protected]123456789
AnnaNowak[email protected]987654321

Pliki csv są bardzo przydatne, ze względu na prostą strukturę i łatwość odczytu i zapisu. Z tego względu również w Pythonie bardzo często korzysta się z tego formatu. Przyjrzyjmy się jak najprościej wczytać i zapisać dane do pliku csv.

Python
import csv

# Otwórz plik CSV w trybie odczytu
with open('kontakty.csv', 'r') as csvfile:

    # Utwórz obiekt reader
    reader = csv.reader(csvfile, delimiter=',')

    # Pomiń nagłówek
    next(reader, None)

    # Iteruj po wierszach pliku
    for row in reader:
        print(row)

Wynik:

['Jan', 'Kowalski', '[email protected]', '123456789']
['Anna', 'Nowak', '[email protected]', '987654321']

Poniż przykład pokazuje jak dopisać dane do pliku csv.

Python
# Otwórz plik CSV w trybie dopisywania
with open('kontakty.csv', 'a', newline='', encoding='utf-8') as csvfile:

    # Utwórz obiekt writer
    writer = csv.writer(csvfile, delimiter=',')

    # Zapisz wiersze do pliku
    writer.writerow(['Rafał', 'Marcinkiewicz', '[email protected]', '34545634'])

Po wykonaniu programu plik kontakty.csv będzie wyglądał następująco:

['Jan', 'Kowalski', '[email protected]', '123456789']
['Anna', 'Nowak', '[email protected]', '987654321']
['Rafał', 'Marcinkiewicz', '[email protected]', '34545634']

Peklowanie

Peklowanie (ang. pickling) służy do tzw. serializacji, czyli procesu polegającego na zapisie na dysku dowolnego obiektu Pythona, np. listy, słownika, itp. Taki plik zapisany w postaci strumienia bajtów zawiera wszystkie niezbędne informacje o obiekcie, dzięki czemu można go zrekonstruować, czyli odpeklować i przywrócić do pierwotnej postaci w dowolnym skrypcie Pythona.

W poniższym przykładzie zapiklujemy przykładowy słownik.

Python
# Peklowanie
import pickle

# Tworzenie przykładowego słownika
dane = {
    'imię': 'Jan',
    'wiek': 30,
    'miasto': 'Warszawa'
}

# Zapisywanie słownika do pliku za pomocą pickle
with open('dane.pickle', 'wb') as plik:
    pickle.dump(dane, plik)

W linii 2 importujemy moduł pickle zawierający funkcje niezbędne w procesie peklowania. W linii 5 tworzymy przykładowy słownik. W linii 12 otwieramy plik przy użyciu wcześniej omówionej konstrukcji with open. Zwróćmy uwagę, że plik otwieramy w trybie wb, czyli 'write binary’, z uwagi na to, że pickle to plik binarny. W linii 13 wykonujemy zapis do pliku przy użyciu funkcji plickle.dump.

Proces odwrotny, czyli odpeklowanie, wykonujemy przy użyciu funkcji pickle.load. W przykładzie poniżej wczytujemy dane do zmiennej, której automatycznie przypisana zostaje struktura słownika.

Python
# Odczytywanie słownika z pliku za pomocą pickle
with open('dane.pickle', 'rb') as plik:
    wczytane_dane = pickle.load(plik)

print("Wczytane dane:", wczytane_dane)

Wynik:

Wczytane dane: {'imię': 'Jan', 'wiek': 30, 'miasto': 'Warszawa'}