Not cathing nested StopIteration

Chris Angelico rosuav at gmail.com
Fri Jul 21 04:48:12 EDT 2017


On Fri, Jul 21, 2017 at 6:32 PM, Antoon Pardon
<antoon.pardon at rece.vub.ac.be> wrote:
> This is python 3.4 on a debian box
>
> In the code below, line 36 raises a StopIteration, I would have
> thought that this exception would be caught by line 39 but instead
> I get a traceback.
>
> Did I miss something or is this a bug?
>
> This is the code:

(trimmed to highlight execution flow)

>     try:                                                             # 21
>         fl = open(filename)                                          # 23
>     except FileNotFoundError:                                        # 24
>         try:                                                         # 25
>             fl = open(filename)                                      # 34
>         except FileNotFoundError:                                    # 35
>             lang = next(iglob(os.path.join(lang_path, prefix)))      # 36
>     except StopIteration:                                            # 39
>         fl = ()                                                      # 40

You go into the first "except FileNotFoundError", and then
StopIteration comes from there. The except block starting on line 39
is actually guarding the try on line 21, and won't catch exceptions
that crop up during the handling of line 24's except block.

I would recommend moving the "except StopIteration" *inside* the other
except block, probably with its own try (so it can only catch
exceptions from the next() call). Or, possibly even better: next() can
take a second argument, which is returned if the iterator is
exhausted. So you could replace this:

            lang = next(iglob(os.path.join(lang_path, prefix)))      # 36
            filename = os.path.join(lang_path, lang)                 # 37
            fl = open(filename)                                      # 38

with this:

            lang = next(iglob(os.path.join(lang_path, prefix)), ())
            fl = fl or open(os.path.join(lang_path, lang))

If no language file is found, next() will return the empty tuple. Then
the next line will act only if a non-empty value is returned.

ChrisA



More information about the Python-list mailing list