pythonioioerror

Why am I getting [Errno 9] Bad file descriptor on file.close() - error handling


I have the below code:

version 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()

version 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

Both are failing with [Errno 9] Bad file descriptor. It is caugt by exception handler higher up the stack.

Now, I am passing True (boolean) as local_copy's value. I know it will fail, my goal here however is to handle the error properly.

I ended up doing the below, but do not find this the best solution. I'd like to know why the initial try...catch block cannot catch this. Is there a different, better way to handle 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 also does not catch anything, as well as Exception.

Standalone example:

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")

Output:

$ 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

Why am I getting exception ignored? Also, why the content of soup is being send to stdout?


Solution

  • Your code:

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

    creates a file object from the value True which is identical to integer 1, which represents a file descriptor for the standard output, i.e. the channel where all prints emit the messages by default.

    (Usually open is used with a filename - I guess you did not intend to write to the standard output.)

    When you close that file, you close your standard output. The first print after that point will fail:

    print("Done")
    

    because it cannot print to closed output. This is the cause for the exception reported.