diff --git a/11-soubory/11-soubory.tex b/11-soubory/11-soubory.tex
new file mode 100644
index 0000000000000000000000000000000000000000..5efb5a953f415072101b5cfc6a8a186f6f1afbc3
--- /dev/null
+++ b/11-soubory/11-soubory.tex
@@ -0,0 +1,276 @@
+\documentclass{beamer}
+\usepackage[utf8]{inputenc}
+\usepackage[czech]{babel}
+\usepackage{palatino}
+\usepackage{verbatim}
+\usetheme{Warsaw}
+\title{Programování 1: Soubory a výjimky}
+\author[Martin Mareš]{Martin Mareš\\\texttt{mj@ucw.cz}}
+\institute{Katedra Aplikované Matematiky\\MFF UK Praha}
+\date{2019}
+\begin{document}
+\setbeamertemplate{navigation symbols}{}
+\setbeamertemplate{footline}{}
+\setbeamerfont{title page}{family=\rmfamily}
+\shorthandoff{"}
+
+\begin{frame}
+\titlepage
+\end{frame}
+
+\input ../slidemac.tex
+
+% ----------------------------------------------------------------------
+
+\begin{frame}{Soubory}
+
+Soubor je pojmenovaná posloupnost {\bf bajtů} (8-bitových hodnot).
+
+~
+
+Nás budou zajímat hlavně {\bf textové soubory:}
+
+\begin{itemize}
+
+\item Skládají se ze {\bf znaků} převedených na bajty nějakým {\bf kódováním},
+nejčastěji:
+
+	\begin{itemize}
+	\item ASCII (\uv{\kern1pt anglická abeceda} o~95 znacích)
+	\item iso-8859-2 (navíc znaky východoevropských jazyků)
+	\item cp1250 (něco podobného specifického pro Windows)
+	\item UTF-8 (vícebajtové znaky, pokrývá většinu jazyků světa)
+	\end{itemize}
+
+\item Soubor je členěn na řádky, každý končí speciálním {\bf znakem konce řádku}
+(pozor, různé operační systémy ukončují řádky různě, ale Python to překládá).
+
+\end{itemize}
+
+\end{frame}
+
+% ----------------------------------------------------------------------
+
+\begin{frame}{Jednoduchý příklad}
+
+\verbatiminput{file-triv.py}
+
+{\bf open} otevírá soubor, dostává:
+
+\begin{itemize}
+\item jméno souboru
+\item mód přístupu:
+	\begin{itemize}
+	\item {\tt r} = čtení
+	\item {\tt w} = zápis (založí/vyprázdní soubor)
+	\item {\tt a} = zápis na konec (append)
+	\item {\tt r+/w+} = čtení i zápis
+	\item {\tt rb} = binární čtení (bajty, ne text)
+	\end{itemize}
+\item {\tt encoding=}kódování (default: podle OS)
+\end{itemize}
+
+\bigskip
+
+Explicitnimu {\bf close} se můžeme vyhnout takto:
+
+\verbatiminput{file-with.py}
+
+\end{frame}
+
+% ----------------------------------------------------------------------
+
+\begin{frame}{Co můžeme dělat se souborem}
+
+Metody souborů:
+
+\begin{itemize}
+
+\item {\tt f.write(text)} -- zapíše text
+
+\item {\tt f.read(n)} -- přečte dalších $n$ znaků ({\tt ""} na konci)
+
+\item {\tt f.read()} -- přečte všechny zbývající znaky
+
+\item {\tt f.readline()} -- přečte další řádek (včetně {\tt {\char92}n}) nebo {\tt ""}
+
+\item {\tt f.seek(...)} -- přesune se na danou pozici v~souboru
+
+\end{itemize}
+
+\bigskip
+
+Další operace:
+
+\begin{itemize}
+
+\item {\tt print(..., file=f)}
+
+\item {\tt for line in f:} -- cyklus přes řádky souboru
+
+\end{itemize}
+
+\bigskip
+
+Pozor, řádky končí na {\tt "{\char92}n"}, hodí se zavolat {\tt rstrip()}.
+
+\end{frame}
+
+% ----------------------------------------------------------------------
+
+\begin{frame}{Standardní vstup a výstup}
+
+Vždy je k~dispozici:
+
+\medskip
+
+\begin{itemize}
+
+\item {\tt sys.stdin} -- standardní vstup (odtud čte {\tt input()})
+
+\item {\tt sys.stdout} -- standardní výstup (sem píše {\tt print()})
+
+\item {\tt sys.stderr} -- standardní chybový výstup
+
+\end{itemize}
+
+\end{frame}
+
+% ----------------------------------------------------------------------
+
+\begin{frame}{Formátování}
+
+\py{%
+"\{\} leží \{\}".format("kočka", "na okně")
+}{%
+'kočka leží na okně'
+}
+
+\py{%
+"\{1\} leží \{0\}".format("kočka", "na okně")
+}{%
+'na okně leží kočka'
+}
+
+\py{%
+"\{kdo\} leží \{kde\}".format(kdo="pes", kde="v boudě")
+}{%
+'pes leží v boudě'
+}
+
+\py{%
+kdo="lenochod"\\
+kde="na větvi"\\
+f"\{kdo\} leží \{kde\}"
+}{%
+'lenochod leží na větvi'
+}
+
+\py{%
+"\{0:05\} < \{1:05\}".format(1, 2)
+}{%
+'00001 < 00002'  \cmt{(další varianty viz dříve)}
+}
+
+\end{frame}
+
+% ----------------------------------------------------------------------
+
+\begin{frame}{Hlášení chyb}
+
+{\bf test.py:}
+
+\verbatiminput{test.py}
+
+\medskip
+
+{\bf Po spuštění dostaneme:}
+
+\verbatiminput{test.err}
+
+\end{frame}
+
+% ----------------------------------------------------------------------
+
+\begin{frame}{Výjimky}
+
+Chyba vygeneruje {\bf výjimku}, například těchto typů:
+
+\medskip
+
+\begin{itemize}
+
+\item ZeroDivisionError -- dělení nulou
+
+\item ValueError -- chybný argument (třeba {\tt log(-4)})
+
+\item IndexError -- přístup k~indexu mimo rozsah
+
+\item KeyError -- čtení neexistujícího klíče ve slovníku
+
+\item FileNotFoundError -- otevření neexistujícího souboru
+
+\item MemoryError -- došla paměť
+
+\item KeyboardInterrupt -- běh programu přerušen pomocí Ctrl-C
+
+\end{itemize}
+
+\end{frame}
+
+% ----------------------------------------------------------------------
+
+\begin{frame}{Odchycení výjimky}
+
+\verbatiminput{exception.py}
+
+\medskip
+
+Výjimky jsou objekty, jejich typy jsou třídy.
+
+\medskip
+
+Výjimka se umí převést na řetězec ({\tt print} ji vypíše).
+
+\medskip
+
+Výjimka má atributy (detaily toho, co se stalo a kde).
+
+\medskip
+
+Typy výjimek tvoří hierarchii (třeba {\tt FileNotFoundError} je potomkem {\tt OSError}),
+{\tt except} umí zachytit i obecnější typ.
+
+\end{frame}
+
+% ----------------------------------------------------------------------
+
+\begin{frame}{Vyvolání výjimky}
+
+\py{%
+raise RuntimeError("Jejda!")
+}{%
+Traceback (most recent call last):\\
+~~File "<stdin>", line 1, in <module>\\
+RuntimeError: Jejda!
+}
+
+\py{%
+assert 1 == 2
+}{%
+[...]\\
+AssertionError
+}
+
+\py{%
+assert 1 == 2, "Svět se nezbláznil"
+}{%
+[...]\\
+AssertionError: Svět se nezbláznil
+}
+
+\end{frame}
+
+% ----------------------------------------------------------------------
+
+\end{document}
diff --git a/11-soubory/Makefile b/11-soubory/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..6aaef9dc02b2389164bffcc77207102f357648a0
--- /dev/null
+++ b/11-soubory/Makefile
@@ -0,0 +1,3 @@
+SLIDES=11-soubory.pdf
+
+include ../Makerules
diff --git a/11-soubory/exception.py b/11-soubory/exception.py
new file mode 100644
index 0000000000000000000000000000000000000000..8483f86e868b3dbe00741a838120c5bacdbf4cc3
--- /dev/null
+++ b/11-soubory/exception.py
@@ -0,0 +1,8 @@
+try:
+    x, y = map(int, input().split())
+    print(x/y)
+except ZeroDivisionError:
+    print("Nulou dělit neumím.")
+except ValueError as x:
+    print("Chyba:", x)
+    print("Zadejte prosím dvě čísla.")
diff --git a/11-soubory/file-triv.py b/11-soubory/file-triv.py
new file mode 100644
index 0000000000000000000000000000000000000000..4602ac8d05447f3631011f7870443b96bcbe4eed
--- /dev/null
+++ b/11-soubory/file-triv.py
@@ -0,0 +1,3 @@
+f = open('soubor.txt', 'w')
+f.write('Hej mistře!\n')
+f.close()
diff --git a/11-soubory/file-with.py b/11-soubory/file-with.py
new file mode 100644
index 0000000000000000000000000000000000000000..d55bb6622ecc5a87fe285394e847dc911f8950c8
--- /dev/null
+++ b/11-soubory/file-with.py
@@ -0,0 +1,2 @@
+with open('soubor.txt', 'w') as f:
+    f.write('Hej mistře!\n')
diff --git a/11-soubory/test.err b/11-soubory/test.err
new file mode 100644
index 0000000000000000000000000000000000000000..5a4c61ae4b3893438c7ff90afa0d2b6d0a80d6c9
--- /dev/null
+++ b/11-soubory/test.err
@@ -0,0 +1,6 @@
+Traceback (most recent call last):
+  File "test.py", line 4, in <module>
+    f(1, 0)
+  File "test.py", line 2, in f
+    print(x/y)
+ZeroDivisionError: division by zero
diff --git a/11-soubory/test.py b/11-soubory/test.py
new file mode 100644
index 0000000000000000000000000000000000000000..e8f45ebd8b78a5714d1643bd72129d7bc1b13aed
--- /dev/null
+++ b/11-soubory/test.py
@@ -0,0 +1,4 @@
+def f(x, y):
+    print(x/y)
+
+f(1, 0)