Search
Na cvičení často používáme termíny “standardní vstup” a “standardní výstup”. Jsou to tzv. streamy (proudy), které vytváří operační systém pro všechny spouštěné procesy. V dokumentaci typicky najdeme označení stdin a stdout, tedy “standard input” a “standard output”. Kromě těchto dvou streamů existuje ještě třetí, chybový, který se označuje jako stderr a slouží pro chybové výpisy.
stdin
stdout
stderr
V počítačových vědách je stream obecný koncept a existují dva základní druhy, vstupní a výstupní. Pokud je stream vstupní, lze z něj číst. Pokud je stream výstupní, lze do něj zapisovat. Pro představu nám může posloužit například potrubní pošta: z jednoho (vstupního) potrubí přichází nové zprávy, které můžeme číst, a do jiného (výstupního) potrubí můžeme své zprávy vhazovat a odesílat je.
V případě třech standardních streamů platí, že stdin je vstupní stream a stdout i stderr jsou výstupní. To by mělo být konzistentní s vaší intuicí: vždy jsme ze standardního vstupu četli a výsledky jsme zapisovali na standardní výstup. Se streamem stderr jste se jistě už také setkali. Pro ilustraci např.:
>>> 1 / 0 Traceback (most recent call last): File "<stdin>", line 1, in <module> ZeroDivisionError: division by zero
Chybová hláška “Traceback … division by zero” byla vypsána na chybový výstup (vizuálně se ale pravděpodobně neliší od standardního výstupu).
Pokud chceme číst řádky ze vstupního streamu, lze použít for cyklus:
for
import sys for line in sys.stdin: print("A line from stdin:", line)
Po spuštění bude program číst vstup z klávesnice, tak dlouho, dokud nedojde na konec streamu stdin. Konec streamu stdin nastane, když se rozhodneme, že už nechceme zadávat žádný další vstup a stiskneme CTRL + D (Linux, Mac?) nebo CTRL + Z (Windows?).
CTRL + D
CTRL + Z
Pro zápis na standardní výstup jsme používali funkci print:
print
print("Hello world")
Pokud bychom chtěli vypsat (z jakéhokoliv důvodu) výstup do jiného streamu, než je stdout, lze použít:
import sys print("Hello world", file=sys.stderr)
Všimněte si, že argument, který jsme použili, se jmenuje file (soubor). Níže zjistíte proč.
file
Pro další a detailnější informace viz LINFO.
Existují i jiné streamy než ty standardní. Jako streamy lze vnímat i soubory: v případě čtení jde o vstupní streamy, v případě zápisu o výstupní.
Pro získání streamu soubor otevřeme pomocí funkce open (viz dokumentace).
open
f_in = open("cesta/k/souboru.txt", "r") # "r" znamená otevření pro čtení f_out = open("cesta/k/souboru2.txt", "w") # "w" znamená otevření pro zápis
Při otevírání souboru specifikujeme režim, ve kterém chceme soubor otevřít (dokumentace uvádí i další režimy kromě “r” a “w”).
Nyní lze využívat vše, co jsme si ukázali pro streamy.
# Čtení řádek ze souboru f_in = open("cesta/k/souboru.txt", "r") for line in f_in: print(line) # Zápis řádek do souboru f_out = open("cesta/k/souboru2.txt", "w") print("Hello world!", file=f_out)
Předchozí výpis není zcela správně, protože je důležité, abychom soubory po použití nezapomněli zavřít. K tomu slouží funkce close.
close
# Čtení řádek ze souboru f_in = open("cesta/k/souboru.txt", "r") for line in f_in: print(line) f_in.close() # Zápis řádek do souboru f_out = open("cesta/k/souboru2.txt", "w") print("Hello world!", file=f_out) f_out.close()
Otevřením souboru nám operační systém poskytuje své prostředky a uzavřením je navracíme zpět. Pokud bychom soubory neuzavřeli, můžou se naše programy chovat neočekávaně (např. ve výstupním souboru chybí některá data, která jsme určitě zapsali) nebo můžou i selhat (kvůli nedostatku paměti nebo file descriptorů).
Je potřeba myslet také na následující situace:
def func(): f_out = open("cesta/k/souboru2.txt", "w") slozity_vypocet_ktery_skonci_chybou() f_out.close()
Funkce slozity_vypocet_ktery_skonci_chybou vyhodí chybu a soubor se neuzavře (f_out.close() se nikdy neprovede). Abychom tomuto předešli, použijeme tzv. with statement a předchozí kód upravíme na:
slozity_vypocet_ktery_skonci_chybou
f_out.close()
with
def func(): with open("cesta/k/souboru2.txt", "w") as f_out: slozity_vypocet_ktery_skonci_chybou()
Python se postará o uzavření souboru za nás.
Vaše domácí úkoly jsou testovány automaticky. BRUTE spustí váš program a vloží zadání na standardní vstup vašeho programu. Poté čte výsledky ze standardního výstupu vašeho programu a porovnává je se správnými výsledky. Proto následující řešení nebude hodnoceno jako korektní:
# volání input("Enter number:") zapíše řetězec "Enter number:" na standardní výstup number = int(input("Enter number:")) result = compute_result(number) print(result)
Mějme soubor pole.txt obsahující čísla oddělená mezerou:
pole.txt
1 3 5 -4 2 5 3
Pro načtení lze použít
with open("pole.txt", "r") as f: line = f.readline() # line = "1 3 5 -4 2 5 3\n" # Zde už je soubor uzavřený words = line.split() # words = ["1", "3", "5", "-4", "2", "5", "3"] pole = list(map(int, words)) # pole = [1, 3, 5, -4, 2, 5, 3] # To samé, ale úspornější zápis with open("pole.txt", "r") as f: pole = list(map(int, f.readline().split()))
Mějme soubor pole.txt obsahující čísla oddělená novým řádkem:
pole = [] with open('pole.txt', 'r') as f: for line in f: pole.append(int(line)) # To samé, ale úspornější zápis with open('pole.txt', 'r') as f: pole = [int(line) for line in f]
Mějme soubor pole.txt obsahující řádky matice oddělené novým řádkem:
1 3 5 -4 2 5
with open("pole.txt", "r") as f: pole = [list(map(int, line.split())) for line in f]