ChatGPT解决这个技术问题 Extra ChatGPT

python exception message capturing

import ftplib
import urllib2
import os
import logging
logger = logging.getLogger('ftpuploader')
hdlr = logging.FileHandler('ftplog.log')
formatter = logging.Formatter('%(asctime)s %(levelname)s %(message)s')
hdlr.setFormatter(formatter)
logger.addHandler(hdlr)
logger.setLevel(logging.INFO)
FTPADDR = "some ftp address"

def upload_to_ftp(con, filepath):
    try:
        f = open(filepath,'rb')                # file to send
        con.storbinary('STOR '+ filepath, f)         # Send the file
        f.close()                                # Close file and FTP
        logger.info('File successfully uploaded to '+ FTPADDR)
    except, e:
        logger.error('Failed to upload to ftp: '+ str(e))

This doesn't seem to work, I get syntax error, what is the proper way of doing this for logging all kind of exceptions to a file

Your indentation is broken. And omit the , after except.
@SvenMarnach, if you omit the , after except, you'll get global name 'e' is not defined, which is not much better than wrong syntax.
@Val: Should be except Exception as e or except Exception, e, depending on Python version.
Probably it's somewhere around those 8 answers, but when you open a file, close part should never be inside the try statement, but either in a finally statement or wrapped by a with statement.
You can do it like UnitTests in requests package do fixexception.com/requests/expected-exception

B
Barış Şenyerli

You have to define which type of exception you want to catch. So write except Exception, e: instead of except, e: for a general exception (that will be logged anyway).

Other possibility is to write your whole try/except code this way:

try:
    with open(filepath,'rb') as f:
        con.storbinary('STOR '+ filepath, f)
    logger.info('File successfully uploaded to '+ FTPADDR)
except Exception, e: # work on python 2.x
    logger.error('Failed to upload to ftp: '+ str(e))

in Python 3.x and modern versions of Python 2.x use except Exception as e instead of except Exception, e:

try:
    with open(filepath,'rb') as f:
        con.storbinary('STOR '+ filepath, f)
    logger.info('File successfully uploaded to '+ FTPADDR)
except Exception as e: # work on python 3.x
    logger.error('Failed to upload to ftp: '+ str(e))

repr(e) gives you the exception(and the message string); str(e) only gives the message string.
As an alternative for logging exception you could use logger.exception(e) instead. It will log the exception with traceback at the same logging.ERROR level.
@mbdevpl this doesn't seem to be true. It appears to call str() on the exception: ideone.com/OaCOpO
except Exception, e: throws a Syntax error to me in python 3. Is this expected?
@CharlieParker in Python3 write except Exception as e:
s
sjtaheri

The syntax is no longer supported in python 3. Use the following instead.

try:
    do_something()
except BaseException as e:
    logger.error('Failed to do something: ' + str(e))

Actually, you should use logger.error('Failed to do something: %s', str(e)) That way, if your logger level is above error it doesn't do the string interpolation.
@avyfain - You are incorrect. The statement logging.error('foo %s', str(e)) will always convert e to a string. To achieve what you are afterm you would use logging.error('foo %s', e) - thereby allowing the logging framework to do (or not do) the conversion.
As an alternative for logging exception you could use logger.exception(e) instead. It will log the exception with traceback at the same logging.ERROR level.
I think he/she meant "except Exception, e:"
Beware that except BaseException and except Exception are not on the same level. except Exception does work in Python3, but it won't catch KeyboardInterrupt for instance (which can be very convenient if you want to be able to interrupt your code!), whereas BaseException catches any exception. See this link for the hierarchy of exceptions.
z
ziedaniel1

If you want the error class, error message, and stack trace, use sys.exc_info().

Minimal working code with some formatting:

import sys
import traceback

try:
    ans = 1/0
except BaseException as ex:
    # Get current system exception
    ex_type, ex_value, ex_traceback = sys.exc_info()

    # Extract unformatter stack traces as tuples
    trace_back = traceback.extract_tb(ex_traceback)

    # Format stacktrace
    stack_trace = list()

    for trace in trace_back:
        stack_trace.append("File : %s , Line : %d, Func.Name : %s, Message : %s" % (trace[0], trace[1], trace[2], trace[3]))

    print("Exception type : %s " % ex_type.__name__)
    print("Exception message : %s" %ex_value)
    print("Stack trace : %s" %stack_trace)

Which gives the following output:

Exception type : ZeroDivisionError
Exception message : division by zero
Stack trace : ['File : .\\test.py , Line : 5, Func.Name : <module>, Message : ans = 1/0']

The function sys.exc_info() gives you details about the most recent exception. It returns a tuple of (type, value, traceback).

traceback is an instance of traceback object. You can format the trace with the methods provided. More can be found in the traceback documentation .


Using e.__class__.__name__ can return the exception class as well.
S
Slipstream

There are some cases where you can use the e.message or e.messages.. But it does not work in all cases. Anyway the more safe is to use the str(e)

try:
  ...
except Exception as e:
  print(e.message)

The problem with this is, for example, if you except Exception as e, and e is an IOError, you get e.errno, e.filename, and e.strerror, but apparently no e.message (at least in Python 2.7.12). If you want to capture the error message, use str(e), as in the other answers.
@epalm What if you catch the IOError before Exception?
@HeribertoJuárez Why catch special cases while you can simply cast it to string?
b
berniey

Updating this to something simpler for logger (works for both python 2 and 3). You do not need traceback module.

import logging

logger = logging.Logger('catch_all')

def catchEverythingInLog():
    try:
        ... do something ...
    except Exception as e:
        logger.error(e, exc_info=True)
        ... exception handling ...

This is now the old way (though still works):

import sys, traceback

def catchEverything():
    try:
        ... some operation(s) ...
    except:
        exc_type, exc_value, exc_traceback = sys.exc_info()
        ... exception handling ...

exc_value is the error message.


This would be my preferred method. Just printing the string is useful for logging I suppose, but if I need to do anything with that information I need more than just a string.
You don't need to 'import traceback' in the second example, right?
P
Peter

You can use logger.exception("msg") for logging exception with traceback:

try:
    #your code
except Exception as e:
    logger.exception('Failed: ' + str(e))

Coincidently, e.msg is the string representation of Exception class.
Or simply logger.exception(e).
C
Chuan Ma

After python 3.6, you can use formatted string literal. It's neat! (https://docs.python.org/3/whatsnew/3.6.html#whatsnew36-pep498)

try
 ...
except Exception as e:
    logger.error(f"Failed to upload to ftp: {e}")

V
Vikramaditya Gaonkar

Using str(e) or repr(e) to represent the exception, you won't get the actual stack trace, so it is not helpful to find where the exception is.

After reading other answers and the logging package doc, the following two ways works great to print the actual stack trace for easier debugging:

use logger.debug() with parameter exc_info

try:
    # my code
except SomeError as e:
    logger.debug(e, exc_info=True)

use logger.exception()

or we can directly use logger.exception() to print the exception.

try:
    # my code
except SomeError as e:
    logger.exception(e)

H
Heini Høgnason

You can try specifying the BaseException type explicitly. However, this will only catch derivatives of BaseException. While this includes all implementation-provided exceptions, it is also possibly to raise arbitrary old-style classes.

try:
  do_something()
except BaseException, e:
  logger.error('Failed to do something: ' + str(e))

s
starriet

If you want to see the original error message, (file & line number)

import traceback
try:
    print(3/0)
except Exception as e:    
    traceback.print_exc() 

This will show you the same error message as if you didn't use try-except.


N
Niraj Trivedi

Use str(ex) to print execption

try:
   #your code
except ex:
   print(str(ex))

s
syter

for the future strugglers, in python 3.8.2(and maybe a few versions before that), the syntax is

except Attribute as e:
    print(e)