Nauč se Python > Kurzy > Začátečnický kurz PyLadies > Soubory a výjimky > Zpětná vazba k domácím projektům

Zpětná vazba k lekci Soubory a výjimky

Zacyklené volání funkcí mezi sebou (chyba v algoritmu)

Nežádoucí tzv. rekurze. Python se nezadře, vyhodí časem výjimku RecursionError.

In [2]:
def sibenice():
    vyhodnoceni()
    sibenice()  # pokus o opětovné spuštění hry

def vyhodnoceni():
    sibenice()  # pokus o opětovné spuštění hry

sibenice()
---------------------------------------------------------------------------
RecursionError                            Traceback (most recent call last)
<ipython-input-2-b4e485a85e09> in <module>
      6     sibenice()  # pokus o opětovné spuštění hry
      7 
----> 8 sibenice()

<ipython-input-2-b4e485a85e09> in sibenice()
      1 def sibenice():
----> 2     vyhodnoceni()
      3     sibenice()  # pokus o opětovné spuštění hry
      4 
      5 def vyhodnoceni():

<ipython-input-2-b4e485a85e09> in vyhodnoceni()
      4 
      5 def vyhodnoceni():
----> 6     sibenice()  # pokus o opětovné spuštění hry
      7 
      8 sibenice()

... last 2 frames repeated, from the frame below ...

<ipython-input-2-b4e485a85e09> in sibenice()
      1 def sibenice():
----> 2     vyhodnoceni()
      3     sibenice()  # pokus o opětovné spuštění hry
      4 
      5 def vyhodnoceni():

RecursionError: maximum recursion depth exceeded

Co když hledáme znak, ale hráč zadá Enter a vyhodnocuje se prázdný řetězec?

In [ ]:
vstup = input('Zadej písmeno: ')    # po stisku Enter je vstup == ''

'd' in 'čokoláda'       # True
'x' in 'čokoláda'       # False
'' in 'čokoláda'        # True (sic!)

'čokoláda'.index('a')   # 7
'čokoláda'.index('č')   # 0
'čokoláda'.index('')    # 0 (sic!)

'čokoláda'.count('')    # 9 (sic!)

Pozor na záludné osamocené zpětné lomítko!

In [3]:
obesenec = """
+---.
|   |
|   O
| --|--
|  / \
|
~~~~~~~"""  # oběšenec s dřevěnou nohou z ráhna šibenice :-)

print(obesenec)
+---.
|   |
|   O
| --|--
|  / |
~~~~~~~

Referenční hodnoty ("etalony") nutno očistit

In [55]:
katakana = """ァアィイゥウェエォオカガキギクグ
            ケゲコゴサザシジスズセゼソゾタダチ
            ヂッツヅテデトドナニヌネノハバパヒ
            ビピフブプヘベペホボポマミムメモャ
            ヤュユョヨラリルレロヮワヰヱヲンヴ
            ヵヶヷヸヹヺ"""

# text je "ァアィ  イゥ"
for znak in text:
    if znak in katakana:
        pocet_katakana += 1  # chybně se započítávají i ' ' a '\n'

print(pocet_katakana)
7

Jedno z jednodušších řešení:

In [50]:
katakana = ''.join(katakana.split())
print(katakana)
ァアィイゥウェエォオカガキギクグケゲコゴサザシジスズセゼソゾタダチヂッツヅテデトドナニヌネノハバパヒビピフブプヘベペホボポマミムメモャヤュユョヨラリルレロヮワヰヱヲンヴヵヶヷヸヹヺ

Hra Šibenice: Při otevírání souborů je vhodné ošetřit výjimku FileNotFoundError

Konkrétně u kódu hry Šibenice se jednalo o výjimku, která neovlivňuje / neohrožuje fungování hry, takže je vhodné tuto výjimku ošetřit.

Chybový výstup by měl podávat co nejvíc relevantních informací. Uživatelský výstup by měl být natolik sdílný, aby bylo možno chybu dohledat, ale neměl by vyzrazovat citlivé informace o aplikaci samotné nebo datech.

Aplikace by měla být připravena na to, že chybí nebo nefunguje nějaká její klíčová kompomenta nebo nemá potřebná data.

In [29]:
try:
    with open("obrazek" + str(chyba) + ".txt", encoding="utf-8") as soubor:
        obsah = soubor.read()
except FileNotFoundError:
    print("Nebyl nalezen obrázek k počtu chyb", chyba)
Nebyl nalezen obrázek k počtu chyb 0

Řešení pomocí modulu logging

In [42]:
import logging  # modul pro sbirani zaznamu o behu programu, varovanich, chybach a vyjimkach
                # uzivateli, do souboru, na vzdaleny server atd. (jsou mozne kombinace vseho)

try:
    with open("katalogovy-list-" + produkt[0:4] + ".txt", encoding="utf-8") as soubor:
        obsah = soubor.read()
except FileNotFoundError as e:
    #
    # tady program vrati chybovou hlasku na web stranku, napr.:
    #     Pri importu produktu SN56132746-54600-5 doslo k chybe. Import bude zastaven.
    #
    logging.exception("Soubor s nezbytnými daty '{}' nebyl nalezen. Produkt: {}".format(e.filename, produkt))
    raise  # chceme vyvolat vyjimku, protoze bez dat program nemuze dale pokracovat
           # hrozi nekonzistence dat pri neuplnem importu
ERROR:root:Soubor s nezbytnými daty 'katalogovy-list-SN56.txt' nebyl nalezen. Produkt: SN56132746-54600-5
Traceback (most recent call last):
  File "<ipython-input-42-beb0234b3389>", line 5, in <module>
    with open("katalogovy-list-" + produkt[0:4] + ".txt", encoding="utf-8") as soubor:
FileNotFoundError: [Errno 2] No such file or directory: 'katalogovy-list-SN56.txt'
---------------------------------------------------------------------------
FileNotFoundError                         Traceback (most recent call last)
<ipython-input-42-beb0234b3389> in <module>
      3 
      4 try:
----> 5     with open("katalogovy-list-" + produkt[0:4] + ".txt", encoding="utf-8") as soubor:
      6         obsah = soubor.read()
      7 except FileNotFoundError as e:

FileNotFoundError: [Errno 2] No such file or directory: 'katalogovy-list-SN56.txt'

Elegantní načtení souboru sibenice.txt (s pomocí seznamů, které se naučíme dnes 😺)

In [ ]:
with open('sibenice.txt', encoding='utf-8') as soubor:
    obsah_souboru = soubor.read()
sibenice = obsah_souboru.split('------------------')

sibenice[5]     # obsahuje textový obrázek šibenice, úroveň 5

Toto je stránka lekce z kurzu, který probíhá nebo proběhl naživo s instruktorem.