How to log error to file, and not fail on exception
Asked Answered
K

5

46

I am downloading a file from the net, and it fails even though I am doing:

for p in query:

    try:
    
    except IOError as e:
       print e;

If there is an error, I want to log it, and then continue on with the next file.

In this loop, I am trying to download an image, if for some reason the filename was bad, or the website was down, etc., I want to continue with the next item in the for loop.

Is there a more generic error that won't fail and continue processing?

Also, how can I log errors to a file?

Kurgan answered 1/8, 2010 at 21:47 Comment(6)
Once the error occurs, you cannot continue -- the download is broken. What specific error are you getting?Isodiametric
I have this in a for loop, why can't I catch the error, then continue and try the next file?Kurgan
@Blankman: Since you didn't provide any code, it's impossible to guess why you can't "catch the error, then continue and try the next file".Isodiametric
@Isodiametric your right my bad, I updated the question.Kurgan
@Blankman: Since you still didn't provide enough code, we still can't determine why your loop doesn't work.Isodiametric
@Blankman: What is the error message (traceback) you get when the script stops? Is it an urllib2.HTTPError for instance? At the moment it seems you may only be catching IOError.Chowder
C
37

As pointed out by Lott, if a download is failing, unless the problem is fixed upstream (or with your download address), the best you can do is to try again. However, if the situation is that you have a list of downloads, and simply want to skip over failed downloads instead of exiting, then:

logf = open("download.log", "w")
for download in download_list:
    try:
        # code to process download here
    except Exception as e:     # most generic exception you can catch
        logf.write("Failed to download {0}: {1}\n".format(str(download), str(e)))
        # optional: delete local version of failed download
    finally:
        # optional clean up code
        pass

Things to note:

(1) Use of the "logging" module, as suggested by ~unutbu, gives you much more flexibility and power with your logging output, including time stamp, simultaneously writing to different channels (e.g., stderr, file) depending on error levels, etc. etc.

(2) You might consider implementing the above logic using the "with" construct.

Coracle answered 1/8, 2010 at 22:9 Comment(4)
what is logf, can't find it anywhere when searching for 'python logf' in google.Kurgan
ah, its just a variable thought it was using logging sorry.Kurgan
Thanks Jeet. It worked for me, but after adding logf.close(). Closing the file is important.Seeress
it does what I want it to do, thanks! But how would I continue the code after the error is logged?Dice
C
58

You could use the logging module:

import logging
logging.basicConfig(filename='/tmp/myapp.log', level=logging.DEBUG, 
                    format='%(asctime)s %(levelname)s %(name)s %(message)s')
logger=logging.getLogger(__name__)

try:
    1/0
except ZeroDivisionError as err:
    logger.error(err)

Running the script writes in /tmp/myapp.log:

% cat /tmp/myapp.log 
2010-08-01 17:50:45,960 ERROR __main__ integer division or modulo by zero
Chowder answered 1/8, 2010 at 21:51 Comment(3)
Nice. But the download is still broken. This won't magically make it "[not] fail and continue processing".Isodiametric
Why do I have to manually write the error to the log file. In batch script you could set it up such that all errors automatically get written to the Log file. You do that by putting your error prone code or your entire code within brackets and redirecting the error stream to a log file. Is there no way to implement this in Python, such that all errors automatically get written in a log file.Worms
@Ghos3t: You might be looking for how to redirect stderr or how to log uncaught exceptions. If that is not what you are looking for, please ask a new question with all the details.Chowder
C
37

As pointed out by Lott, if a download is failing, unless the problem is fixed upstream (or with your download address), the best you can do is to try again. However, if the situation is that you have a list of downloads, and simply want to skip over failed downloads instead of exiting, then:

logf = open("download.log", "w")
for download in download_list:
    try:
        # code to process download here
    except Exception as e:     # most generic exception you can catch
        logf.write("Failed to download {0}: {1}\n".format(str(download), str(e)))
        # optional: delete local version of failed download
    finally:
        # optional clean up code
        pass

Things to note:

(1) Use of the "logging" module, as suggested by ~unutbu, gives you much more flexibility and power with your logging output, including time stamp, simultaneously writing to different channels (e.g., stderr, file) depending on error levels, etc. etc.

(2) You might consider implementing the above logic using the "with" construct.

Coracle answered 1/8, 2010 at 22:9 Comment(4)
what is logf, can't find it anywhere when searching for 'python logf' in google.Kurgan
ah, its just a variable thought it was using logging sorry.Kurgan
Thanks Jeet. It worked for me, but after adding logf.close(). Closing the file is important.Seeress
it does what I want it to do, thanks! But how would I continue the code after the error is logged?Dice
C
20

This will write your error to a log file and continue to run the code.

import traceback

#This line opens a log file
with open("log.txt", "w") as log:

    try:
        # some code
        # Below line will print any print to log file as well.
        print("Creating DB Connection", file = log)
    except Exception:
        traceback.print_exc(file=log)
        continue
Corinnacorinne answered 24/10, 2017 at 6:58 Comment(2)
A continue statement can't be used outside of loops afaik. Aside from that, it works perfectly. Thanks!Hexastich
use 'pass' , no 'continue'Spiritualist
C
4

This catches everything. But it is much, much better to catch the exact exception. python <= 2.7

while True:
  try:
    doStuff()
  except Exception, e:
    f = open('log.txt', 'w')
    f.write('An exceptional thing happed - %s' % e)
    f.close()
Cyril answered 1/8, 2010 at 23:58 Comment(0)
P
-1

Add a continue statement in the except block. The continue statement will continue the loop at the next item, bypassing any remaining code within the current loop iteration.

for p in query:

    try:
        # The thing that might fail
    except IOError as error:
        print(error)
        continue

For more information, see: How To Use Break, Continue, and Pass Statements when Working with Loops in Python 3

Petersham answered 12/2, 2023 at 2:39 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.