Закрытие потока
Последняя операция, выполненная над потоком (это не включает потоки stdin
, stdout
и stderr
, которые не требуют этого), должна быть закрытием.
Это действие выполняется методом, вызываемым из объекта открытого потока: stream.close()
.
- имя функции определенно комментируется (
close()
); - функция не ожидает точно никаких аргументов; поток не нужно открывать;
- функция ничего не возвращает, но вызывает IOError в случае ошибки;
- большинство разработчиков считают, что функция
close()
всегда выполняется успешно, поэтому нет необходимости проверять, правильно ли она выполнила свою задачу.
Это убеждение только частично оправдано. Если поток был открыт для записи, а затем была выполнена серия операций записи, может случиться, что данные, отправленные в поток, еще не были перенесены на физическое устройство (из-за механизма, называемого кэшированием или буферизацией). Поскольку закрытие потока вынуждает буферы сбрасывать данные, может случиться так, что сбой завершится неудачей, и поэтомуclose()
тоже не удастся.
Мы уже упоминали о сбоях, вызванных функциями, работающими с потоками, но не упомянули ни слова о том, как именно мы можем определить причину сбоя.
Возможность поставить диагноз существует и обеспечивается одним из компонентов исключения потоков, о котором мы собираемся рассказать вам прямо сейчас.
Диагностика проблем с потоками
Объект IOError
оснащен свойством с именем errno
(имя происходит от фразы error number), и Вы можете получить к нему доступ как следующим образом:
try:
# Some stream operations.
except IOError as exc:
print(exc.errno)
Значение атрибута errno
можно сравнить с одной из предопределенных символических констант, определенных в модуле errno
.
Давайте посмотрим на некоторые выбранные константы, полезные для обнаружения потоковых ошибок:
errno.EACCES
→ в доступе отказано.
Ошибка возникает, например, при попытке открыть файл с атрибутом только для чтения для записи.errno.EBADF
→ неверный номер файла.
Ошибка возникает, когда Вы пытаетесь, например, работать с неоткрытым потоком.errno.EEXIST
→ файл существует.
Ошибка возникает, например, при попытке изменить имя файла на такое же.errno.EFBIG
→ файл слишком большой.
Ошибка возникает при попытке создать файл, размер которого превышает максимально допустимый операционной системой.errno.EISDIR
→ это каталог.
Ошибка возникает при попытке трактовать имя каталога как имя обычного файла.errno.EMFILE
→ слишком много открытых файлов.
Ошибка возникает при попытке одновременно открыть больше потоков, чем приемлемо для вашей операционной системы.errno.ENOENT
→ нет такого файла или каталога.
Ошибка возникает при попытке доступа к несуществующему файлу/каталогу.errno.ENOSPC
→ на устройстве не осталось места.
Ошибка возникает, когда на носителе нет свободного места.
Полный список намного длиннее (он также включает некоторые коды ошибок, не связанные с обработкой потока).