0

I am trying to send file object in a rest call and want to receive its response but the POST method may throw some error and file will not be closed after that. So, I added close in except block also. But when I run the code the first api (GET) throws some error and in except it close the file which was never opened and throws another error. I don't know how to handle the close() only when the file is opened.

Here is my Basic Structure of the code:

try:
    url = "some url"
    # This Response may throw some error
    response = requests.get(url = url, headers=headers,params=params)
    file = open("file.txt","r")
    # This Response may throw some error
    response = requests.post(url = url, headers=headers,params=params, files=file)
    file.close()
except:
    file.close()
  • I would suggest to EITHER add nested 'try' statements to handle error sources independently OR open the file using the 'with' statement. The latter handles file closing automatically for you, so you do not need to call 'close': with open("file.txt", "r") as file: ... – insulanus Mar 12 '22 at 14:28
  • @insulanus Eh. Nested `try-except` blocks can be better avoided with multiple excepts. See [this question on the subject](https://stackoverflow.com/questions/6095717/python-one-try-multiple-except) – zurgeg Mar 12 '22 at 14:31
  • Thank you @insulanus. I also saw the implementation of with below. I will Use with only. –  Mar 12 '22 at 14:32

2 Answers2

1

You can set some flag variables to know if the file was successfully opened, and if it needs to be closed:

file_was_opened = False
file_was_closed = False

try:
    # some code that may throw exceptions
    file = open('filename')
    file_was_opened = True
    # some other code that may throw exceptions
    file.close()
    file_was_closed = True
except:
    # handle the exception

if file_was_opened and not file_was_closed:
    file.close()

However, the better way is to use a context manager. This is a special way of opening a file that guarantees it will be closed, no matter what else happens.

with open('filename') as file:
    try:
        # some code that may throw exceptions
    except:
        # handle the exception

# after the "with" block is done, the file is guaranteed to be
# closed
John Gordon
  • 29,573
  • 7
  • 33
  • 58
0

Your first problem is that you are relying on something in your try block happening. If your file doesn't exist, you'll get a different exception (and the exception catch will also fail). To remedy this, first check if your file variable exists at all:

if "file" in locals():

Now if it is, make sure it isn't already closed and close it if it is open.

    # ... within the if block
    if not file.closed:
        file.close()

Now you are free to handle your exception. Another (and frankly better solution) is the with statement, explanined in this answer, but I'll put an example of it here, just for completeness:

with open("myfile.txt") as file:
    try:
        do_things()
    except:
        ...
zurgeg
  • 510
  • 6
  • 18
  • 1
    Checking for 'file' in locals() could be very misleading. What if there was a variable called *file* that existed before the attempt to open the file (and re-use that variable)? – DarkKnight Mar 12 '22 at 15:20
  • @ArthurKing true. That would be bad practice, however, overriding a variable you rely on (to access another file, mind you) later without deleting the old one seems like a bad idea. Say `file` used to contain `nuclear_missile_launch_commands.txt`. Writing to that could cause some [very serious internal side effects!](https://hackage.haskell.org/package/acme-missiles-0.3/docs/Acme-Missiles.html#v:launchMissilesl) – zurgeg Mar 12 '22 at 15:25