Почему я получаю [Errno 9] Неверный дескриптор файла в file.close() — обработка ошибок

#python #io #ioerror

#python #io #ошибка ioerror

Вопрос:

У меня есть приведенный ниже код:

версия A

 try:
    file = open(local_copy, "wt")
    n = file.write(str(soup))
    logging.debug(f't{local_copy} saved. {n} lines saved.')
except IOError as e:
    logging.error(traceback.print_exc())
finally:
    file.close()
  

версия B

 try:
    with open(local_copy, "wt") as file:
        n = file.write(str(soup))
    logging.debug(f't{local_copy} saved. {n} lines saved.')
except IOError as e:
    logging.error(traceback.print_exc())
finally:
    None
  

Оба сбоя с [Errno 9] Неверным файловым дескриптором. Это вызвано обработчиком исключений выше по стеку.

Теперь я передаю True (логическое значение) как значение local_copy . Я знаю, что это не удастся, однако моя цель здесь — правильно обработать ошибку.

В итоге я сделал следующее, но не нахожу это лучшим решением. Я хотел бы знать, почему начальный блок try … catch не может перехватить это. Есть ли другой, лучший способ обработки IOErrors ?

 if not isinstance(local_copy, str):
    logging.error(f"Cannot store localcopy of the file")
    logging.error(f'"local_copy" variable holds a value of an incorrect type: {type(local_copy)} (required str).')
else:
    try:
        file = open(local_copy, "wt")
        n = file.write(str(soup))
        logging.debug(f't{local_copy} saved. {n} lines saved.')
        # with open(local_copy, "wt") as file:
        #     n = file.write(str(soup))
        # 
        # logging.debug(f't{local_copy} saved. {n} lines saved.')
    except IOError as e:
        logging.error(traceback.print_exc())
    finally:
        file.close()
        #None
  

OSError также ничего не улавливает, как и исключение.

Отдельный пример:

 import io

local_copy = True
soup = "Great soup"

try:
    file = open(local_copy, "wt")
    n = file.write(str(soup))
    print(f't{local_copy} saved. {n} lines saved.')
except OSError as e:
    print("we got the error")
finally:
    file.close()
print ("Done")
  

Вывод:

 $ python3 test.py 
True saved. 10 lines saved.
Great soupTraceback (most recent call last):
 File "test.py", line 18, in <module>
    print ("Done")
OSError: [Errno 9] Bad file descriptor
Exception ignored in: <_io.TextIOWrapper name='<stdout>' mode='w' encoding='UTF-8'>
OSError: [Errno 9] Bad file descriptor
  

Почему я игнорирую исключение?
Кроме того, почему содержимое soup отправляется в стандартный вывод?

Комментарии:

1. При попытке закрыть уже закрытый файл может возникнуть неверный дескриптор файла. Но, как упоминалось выше, пожалуйста, предоставьте более подробную информацию о вашем коде.

2. @ThierryLathuille IOError является псевдонимом для OSError начиная с Python 3.3

3. Я обновил вопрос с помощью автономного, работоспособного примера.

Ответ №1:

Ваш код:

 local_copy = True
....
file = open(local_copy, "wt")
  

создает файловый объект из значения True , идентичного integer 1 , который представляет файловый дескриптор для стандартного вывода, то есть канал, по которому все отпечатки по умолчанию отправляют сообщения.

(Обычно open используется с именем файла — я думаю, вы не собирались записывать в стандартный вывод.)

Когда вы закрываете этот файл, вы закрываете стандартный вывод. Первая печать после этой точки завершится ошибкой:

 print("Done")
  

потому что он не может печатать в закрытый вывод. Это причина сообщения об исключении.

Комментарии:

1. хорошо, это отвечает на стандартную часть вопроса — спасибо !. тем не менее, как перехватить первую ошибку в file.close(). Просто для ясности, я понимаю, что приведенный выше код не работает, я пытаюсь улучшить обработку ошибок.

2. @m0rt1m3r Но close сбой не происходит; попробуйте небольшую программу с простым открытием закрытием, без печати. Если у вас есть другой вопрос, пожалуйста, точно опишите, что код должен делать в первую очередь.

3. вы правы:/ Я выполнил дополнительную отладку со своей стороны, и код на самом деле не выполнял следующую инструкцию print дальше по строке (потому что я закрыл стандартный вывод). Я не знал о дескрипторе 1, спасибо. Я добавлю правильную проверку типов в свой код и создам исключение TypeError.