Práce se soubory v Pythonu

Práce se soubory v Pythonu

Úvod do práce se soubory

Práce se soubory je klíčovou dovedností pro prakticky jakékoliv programování. Soubory nám umožňují ukládat a načítat data mezi jednotlivými spuštěními programu, zpracovávat velké objemy dat a sdílet data mezi různými aplikacemi. V Pythonu je práce se soubory poměrně jednoduchá díky vestavěným funkcím a knihovnám.

V tomto článku se naučíme:

Základní operace se soubory

Otevírání souborů

V Pythonu otevíráme soubory pomocí vestavěné funkce open(). Tato funkce přijímá dva hlavní parametry: cestu k souboru a režim otevření.

# Otevření souboru pro čtení (výchozí režim)
soubor = open('data.txt', 'r')

# Nezapomeňte soubor zavřít po dokončení práce
soubor.close()

Režimy otevření souborů:

Kontextový manažer (with statement)

Lepším způsobem práce se soubory je použití příkazu with, který zajistí, že soubor bude správně uzavřen i v případě výskytu chyby.

# Použití kontextového manažeru
with open('data.txt', 'r') as soubor:
    obsah = soubor.read()
    print(obsah)

# Soubor je automaticky uzavřen po opuštění bloku with

Čtení ze souborů

Existuje několik metod pro čtení obsahu ze souborů:

Čtení celého souboru

# Čtení celého obsahu
with open('data.txt', 'r', encoding='utf-8') as soubor:
    obsah = soubor.read()
    print(obsah)

Parametr encoding je důležitý při práci s texty obsahujícími diakritiku nebo jiné speciální znaky. Pro české texty se obvykle používá 'utf-8'.

Čtení po řádcích

# Čtení souboru po řádcích
with open('data.txt', 'r', encoding='utf-8') as soubor:
    for radek in soubor:
        print(radek.strip())  # strip() odstraní bílé znaky na začátku a konci (včetně znaku nového řádku)

Čtení do seznamu řádků

# Načtení všech řádků do seznamu
with open('data.txt', 'r', encoding='utf-8') as soubor:
    radky = soubor.readlines()
    
for radek in radky:
    print(radek.strip())

Čtení konkrétního počtu znaků

# Čtení prvních 10 znaků
with open('data.txt', 'r', encoding='utf-8') as soubor:
    cast = soubor.read(10)
    print(cast)

Zápis do souborů

Zápis textu

# Zápis do souboru (přepíše existující obsah)
with open('vystup.txt', 'w', encoding='utf-8') as soubor:
    soubor.write('Ahoj, světe!\n')
    soubor.write('Tohle je druhý řádek textu.')

Připojení obsahu na konec souboru

# Přidání obsahu na konec souboru
with open('vystup.txt', 'a', encoding='utf-8') as soubor:
    soubor.write('\nTohle je přidaný řádek.')

Zápis více řádků

# Zápis více řádků najednou
radky = ['První řádek', 'Druhý řádek', 'Třetí řádek']

with open('vystup.txt', 'w', encoding='utf-8') as soubor:
    for radek in radky:
        soubor.write(radek + '\n')
        
# Alternativně lze použít writelines()
with open('vystup2.txt', 'w', encoding='utf-8') as soubor:
    # Poznámka: writelines() automaticky nepřidává znaky nového řádku
    soubor.writelines(radek + '\n' for radek in radky)

Práce s cestami k souborům

Pro práci s cestami k souborům a adresářům je v Pythonu vhodné použít modul os.path nebo modernější modul pathlib.

Použití os.path

import os

# Aktuální pracovní adresář
current_dir = os.getcwd()
print(f"Aktuální adresář: {current_dir}")

# Spojení cesty
cesta_k_souboru = os.path.join(current_dir, 'data', 'soubor.txt')
print(f"Cesta k souboru: {cesta_k_souboru}")

# Kontrola existence souboru
if os.path.exists(cesta_k_souboru):
    print(f"Soubor {cesta_k_souboru} existuje.")
else:
    print(f"Soubor {cesta_k_souboru} neexistuje.")
    
# Získání jména souboru a přípony
nazev_souboru = os.path.basename(cesta_k_souboru)
pripona = os.path.splitext(nazev_souboru)[1]
print(f"Název souboru: {nazev_souboru}")
print(f"Přípona: {pripona}")

Použití pathlib

from pathlib import Path

# Aktuální pracovní adresář
current_dir = Path.cwd()
print(f"Aktuální adresář: {current_dir}")

# Spojení cesty
cesta_k_souboru = current_dir / 'data' / 'soubor.txt'
print(f"Cesta k souboru: {cesta_k_souboru}")

# Kontrola existence souboru
if cesta_k_souboru.exists():
    print(f"Soubor {cesta_k_souboru} existuje.")
else:
    print(f"Soubor {cesta_k_souboru} neexistuje.")
    
# Získání jména souboru a přípony
nazev_souboru = cesta_k_souboru.name
pripona = cesta_k_souboru.suffix
print(f"Název souboru: {nazev_souboru}")
print(f"Přípona: {pripona}")

Práce s CSV soubory

CSV (Comma Separated Values) je běžný formát pro ukládání tabulkových dat. Python poskytuje modul csv pro snadnou práci s tímto formátem.

Čtení CSV souboru

import csv

# Čtení CSV souboru
with open('data.csv', 'r', encoding='utf-8', newline='') as csvfile:
    # Pro CSV soubory s hlavičkou
    csv_reader = csv.DictReader(csvfile)
    
    for row in csv_reader:
        print(row)  # row je slovník, kde klíče jsou názvy sloupců
        
# Alternativně bez použití názvů sloupců
with open('data.csv', 'r', encoding='utf-8', newline='') as csvfile:
    csv_reader = csv.reader(csvfile)
    
    for row in csv_reader:
        print(row)  # row je seznam hodnot v řádku

Zápis do CSV souboru

import csv

# Data pro zápis
data = [
    ['Jméno', 'Věk', 'Město'],  # Hlavička
    ['Karel', 30, 'Praha'],
    ['Jana', 25, 'Brno'],
    ['Petr', 35, 'Ostrava']
]

# Zápis do CSV souboru
with open('vystup.csv', 'w', encoding='utf-8', newline='') as csvfile:
    csv_writer = csv.writer(csvfile)
    
    # Zápis všech řádků najednou
    csv_writer.writerows(data)
    
# Zápis s použitím slovníků
data_dict = [
    {'Jméno': 'Karel', 'Věk': 30, 'Město': 'Praha'},
    {'Jméno': 'Jana', 'Věk': 25, 'Město': 'Brno'},
    {'Jméno': 'Petr', 'Věk': 35, 'Město': 'Ostrava'}
]

with open('vystup2.csv', 'w', encoding='utf-8', newline='') as csvfile:
    fieldnames = ['Jméno', 'Věk', 'Město']
    csv_writer = csv.DictWriter(csvfile, fieldnames=fieldnames)
    
    csv_writer.writeheader()  # Zápis hlavičky
    csv_writer.writerows(data_dict)  # Zápis dat

Práce s JSON soubory

JSON (JavaScript Object Notation) je populární formát pro výměnu dat. Python poskytuje modul json pro serializaci a deserializaci JSON dat.

Čtení JSON souboru

import json

# Čtení JSON souboru
with open('data.json', 'r', encoding='utf-8') as jsonfile:
    data = json.load(jsonfile)
    
print(data)  # data je Python objekt (slovník, seznam, atd.)

Zápis do JSON souboru

import json

# Data pro zápis
data = {
    'jmeno': 'Karel',
    'vek': 30,
    'mesto': 'Praha',
    'zajmy': ['programování', 'cestování', 'fotografie'],
    'aktivni': True,
    'vyska': 180.5
}

# Zápis do JSON souboru
with open('vystup.json', 'w', encoding='utf-8') as jsonfile:
    json.dump(data, jsonfile, ensure_ascii=False, indent=4)
    
# ensure_ascii=False umožňuje zápis znaků Unicode (např. diakritika)
# indent=4 zajistí hezké formátování (odsazení) výstupu

Zpracování velkých souborů

Při práci s velkými soubory je důležité myslet na efektivní využití paměti. Místo načtení celého souboru do paměti je lepší zpracovávat ho postupně.

# Efektivní zpracování velkého souboru po řádcích
def zpracuj_velky_soubor(cesta_k_souboru):
    with open(cesta_k_souboru, 'r', encoding='utf-8') as soubor:
        for cislo_radku, radek in enumerate(soubor, 1):
            # Zpracování každého řádku
            radek = radek.strip()
            if not radek:  # Přeskočení prázdných řádků
                continue
                
            # Provést nějakou operaci s řádkem
            print(f"Řádek {cislo_radku}: {radek[:50]}...")  # Zobrazit první část řádku
            
# Volání funkce
zpracuj_velky_soubor('velky_soubor.txt')

Práce s binárními soubory

Pro práci s binárními soubory (např. obrázky, hudba, video) musíte otevřít soubor v binárním režimu.

# Kopírování binárního souboru
def kopiruj_soubor(zdroj, cil):
    with open(zdroj, 'rb') as zdrojovy_soubor:
        with open(cil, 'wb') as cilovy_soubor:
            # Čtení a zápis po blocích
            blok_velikost = 4096  # 4 KB
            while True:
                blok = zdrojovy_soubor.read(blok_velikost)
                if not blok:  # Konec souboru
                    break
                cilovy_soubor.write(blok)
    
    print(f"Soubor {zdroj} byl úspěšně zkopírován do {cil}.")
    
# Volání funkce
kopiruj_soubor('obrazek.jpg', 'kopie_obrazku.jpg')

Praktický příklad: Jednoduchý textový editor

Zde je příklad jednoduchého textového editoru, který umožňuje vytváření, otevírání a editaci textových souborů.

def textovy_editor():
    """Jednoduchý textový editor v příkazové řádce."""
    soubor = None
    obsah = []
    
    print("Jednoduchý textový editor")
    print("Příkazy: novy, otevrit, ulozit, vypsat, pridat, odejit")
    
    while True:
        prikaz = input("\nZadejte příkaz: ").strip().lower()
        
        if prikaz == "novy":
            soubor = input("Zadejte název nového souboru: ")
            obsah = []
            print(f"Vytvořen nový soubor {soubor}")
            
        elif prikaz == "otevrit":
            soubor = input("Zadejte název souboru k otevření: ")
            try:
                with open(soubor, 'r', encoding='utf-8') as f:
                    obsah = f.readlines()
                obsah = [radek.rstrip('\n') for radek in obsah]
                print(f"Soubor {soubor} byl úspěšně otevřen.")
            except FileNotFoundError:
                print(f"Soubor {soubor} nebyl nalezen.")
            except Exception as e:
                print(f"Chyba při otevírání souboru: {e}")
                
        elif prikaz == "ulozit":
            if soubor is None:
                soubor = input("Zadejte název souboru pro uložení: ")
            
            try:
                with open(soubor, 'w', encoding='utf-8') as f:
                    for radek in obsah:
                        f.write(radek + '\n')
                print(f"Soubor {soubor} byl úspěšně uložen.")
            except Exception as e:
                print(f"Chyba při ukládání souboru: {e}")
                
        elif prikaz == "vypsat":
            if not obsah:
                print("Soubor je prázdný nebo nebyl otevřen.")
            else:
                print("\nObsah souboru:")
                for i, radek in enumerate(obsah, 1):
                    print(f"{i}: {radek}")
                    
        elif prikaz == "pridat":
            if soubor is None:
                print("Nejprve vytvořte nový soubor nebo otevřete existující.")
                continue
                
            print("Zadejte obsah (prázdný řádek ukončí zadávání):")
            while True:
                radek = input()
                if not radek:
                    break
                obsah.append(radek)
                
        elif prikaz == "odejit":
            print("Ukončení editoru...")
            break
            
        else:
            print("Neznámý příkaz. Zkuste znovu.")
    
# Spuštění editoru
# textovy_editor()

Tipy a triky pro práci se soubory

Bezpečné čtení a zápis

Vždy používejte kontextový manažer (with) pro práci se soubory, abyste zajistili, že budou správně uzavřeny i v případě chyby.

Zacházení s výjimkami

try:
    with open('neexistujici_soubor.txt', 'r') as soubor:
        obsah = soubor.read()
except FileNotFoundError:
    print("Soubor nebyl nalezen.")
except PermissionError:
    print("Nemáte oprávnění k tomuto souboru.")
except Exception as e:
    print(f"Nastala neočekávaná chyba: {e}")

Relativní a absolutní cesty

Používejte relativní cesty pro přenositelnost nebo absolutní cesty pro jednoznačné určení.

import os

# Relativní cesta (vztažená k aktuálnímu pracovnímu adresáři)
with open('data/soubor.txt', 'r') as f:
    # ...

# Absolutní cesta
absolutni_cesta = os.path.abspath('data/soubor.txt')
with open(absolutni_cesta, 'r') as f:
    # ...

Dočasné soubory

Pro dočasné soubory používejte modul tempfile.

import tempfile

# Vytvoření dočasného souboru
with tempfile.NamedTemporaryFile(mode='w+', delete=False) as temp:
    temp.write('Tohle je dočasný obsah')
    temp_filename = temp.name

# Soubor je uzavřen, ale stále existuje
print(f"Dočasný soubor byl vytvořen jako: {temp_filename}")

# Čtení z dočasného souboru
with open(temp_filename, 'r') as f:
    print(f.read())

# Odstranění dočasného souboru
import os
os.unlink(temp_filename)

Shrnutí

V tomto článku jste se naučili:

Práce se soubory je základní dovednost, kterou budete využívat v mnoha svých programech. Schopnost efektivně číst, zapisovat a manipulovat s daty v souborech vám otevře dveře k vytváření užitečných aplikací, které mohou pracovat s perzistentními daty.

To uzavírá naši sérii základních článků o programování v Pythonu. Doufáme, že vám tyto základy pomohou na cestě k úspěšnému programování v jednom z nejpopulárnějších a nejužitečnějších programovacích jazyků současnosti!