Разница между IOError и OSError?

Я всегда путаюсь, будет ли функция повышать IOError или OSError (или оба?). Каково основное правило, лежащее в основе этих типов исключений, какова разница между ними и когда возникает?

Я изначально думал, что OSError для таких вещей, как отказ в разрешении, но открытие файла без разрешений приведет к увеличению IOError.

Ответ 1

Между этими двумя типами очень мало различий. На самом деле даже разработчики Python согласились с тем, что нет реальной разницы и удалены IOError в Python 3 (теперь это псевдоним для OSError). См. PEP 3151 - Переопределение иерархии исключений ОС и IO:

Хотя некоторые из этих различий могут быть объяснены соображениями реализации, они часто не очень логичны на более высоком уровне. Например, линия, разделяющая OSError и IOError, часто размывается. Рассмотрим следующее:

>>> os.remove("fff")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
OSError: [Errno 2] No such file or directory: 'fff'
>>> open("fff")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
IOError: [Errno 2] No such file or directory: 'fff'

Да, это два разных типа исключений с тем же сообщением об ошибке.

Для вашего собственного кода придерживайтесь метаданных OSError. Для существующих функций проверьте документацию (она должна детализировать то, что вам нужно поймать), но вы можете безопасно поймать оба:

try:
    # ...
except (IOError, OSError):
    # handle error

Повторное цитирование PEP:

На самом деле трудно думать о любой ситуации, когда OSError следует поймать, но не IOError, или наоборот.