Python open() выдает разные ошибки для файла, который не найден - как обрабатывать оба исключения?

У меня есть сценарий, в котором пользователю предлагается ввести имя файла (файла, который нужно открыть), и если файл не существует в текущем каталоге, пользователю предлагается снова. Вот краткая версия:

file = input("Type filename: ")

...
try:
    fileContent = open(filename, "r")
    ...
except FileNotFoundError:
    ...

Когда я тестировал свой скрипт на своей MacOS X в Python 3.3x, он отлично работал, когда я намеренно вводил неправильное имя файла (он запускает пакет под «ожиданием»).

Однако, когда я хотел запустить свой код на компьютере с Windows в Python 3.2x, я получаю сообщение об ошибке, в котором говорится, что «FileNotFoundError» не определен. Итак, Python 3.2 в Windows считает, что «FileNotFoundError» — это переменная, и программа завершает работу с ошибкой.

Я понял, что Python 3.2 в Windows выдает «IOError», если имя входного файла неверно. Я протестировал его на своей Linux-машине в Python 2.7, и это также ошибка IOError.

Моя проблема в том, что код с

except "FileNotFoundError":

не будет работать на Windows Python 3.2, но если я изменю его на

except "IOError":

это больше не будет работать на моем Mac.

Как я мог обойти это? Единственный способ, который я могу придумать, это использовать только except, чего я обычно не хочу.


person Community    schedule 22.02.2013    source источник
comment
Это не из-за Mac/Windows, это версия Python. Я бы также исследовал 3.2/3.3 в OS X (и 3.3 в Windows), ознакомился с журналами изменений, а затем отредактировал вопрос/заголовок соответствующим образом.   -  person    schedule 22.02.2013


Ответы (4)


В версии 3.3 IOError стал псевдонимом для OSError, а FileNotFoundError — подклассом. из OSError. Так что вы можете попробовать

except (OSError, IOError) as e:
   ...

Это создаст довольно широкую сеть, и вы не можете предположить, что исключение «файл не найден» без проверки e.errno, но это может охватывать ваш вариант использования.

PEP 3151 подробно обсуждает обоснование изменения.

person Russell Borogove    schedule 22.02.2013

Это кажется мне лучше простого except:, но я не уверен, что это лучшее решение:

error_to_catch = getattr(__builtins__,'FileNotFoundError', IOError)

try:
    f = open('.....')
except error_to_catch:
    print('!')
person cwallenpoole    schedule 22.02.2013
comment
В других новостях except: с запятой грамматически правильно, но все равно кажется очень странным. - person cwallenpoole; 23.02.2013
comment
Тоже очень хорошее решение. Немного длиннее, чем except(IOError, OSError):, но поэтому более конкретно - person ; 23.02.2013
comment
это антипаттерн. - person omni; 21.01.2021

Итак, чтобы точно поймать только тогда, когда файл не найден, я делаю:

import errno
try:
   open(filename, 'r')
except (OSError, IOError) as e: # FileNotFoundError does not exist on Python < 3.3
   if getattr(e, 'errno', 0) == errno.ENOENT:
      ... # file not found
   raise
person Alex Che    schedule 09.09.2016

можно поймать 2 ошибки одновременно

except (FileNotFoundError, IOError):

Я не понял, что это то, о чем вы спрашивали. Я надеюсь, что есть более красноречивое решение, чем проверять вручную

try:
   error_to_catch = FileNotFoundError
except NameError:
   error_to_catch = IOError

except error_to_catch

cwallenpoole делает это условно более красноречиво в своем ответе (error_to_catch = getattr(__builtins__,'FileNotFoundError', IOError))

person dm03514    schedule 22.02.2013
comment
Будет ли это работать, если: Я получаю сообщение об ошибке, говорящее о том, что FileNotFoundError не определен. Итак, Python 3.2 в Windows считает FileNotFoundError переменной, и программа завершает работу с ошибкой - ? - person ; 22.02.2013
comment
@pst интересно извините не учел - person dm03514; 23.02.2013