Python argparse errors to file

时光总嘲笑我的痴心妄想 提交于 2020-01-15 12:08:34

问题


I am trying to make a script that takes all errors and logs them to a log file. I want to include any argparse errors to this file. I already use the logging package and a sys.excepthook to drive unexpected exceptions to the log file.

Here's an example code:

import argparse
import logging
import sys
import traceback

def log_uncaught_exceptions(ex_cls, ex, tb):
    logging.critical(''.join(traceback.format_tb(tb)))
    logging.critical('{0}: {1}'.format(ex_cls, ex))

logging.basicConfig(
    level=logging.DEBUG,
    filename='foo.log',
    filemode='w',
    format='%(asctime)s - %(levelname)s - %(message)s')

sys.excepthook = log_uncaught_exceptions

logging.debug('This is a typical debug line')

parser = argparse.ArgumentParser(description='Foo String')
parser.add_argument('foo',type=int)
args = parser.parse_args()
logging.debug('Input was %i'%(args.foo))

When I run it with python logger_argparse.py 1 everything works great. If I run python logger_argparse.py a I get the output in the console and not the log file:

usage: logger_argparse.py [-h] foo
logger_argparse.py: error: argument foo: invalid int value: 'a'

How do I get that information to go to the log file?


回答1:


Can you use logging.exception in an exception handler? Edit: so how about just logging from ArgumentParser.error()?

import sys
import logging
import argparse

class argparse_logger(argparse.ArgumentParser):
    def error(self, message):
        logging.error(message)
        super().error(message)

logging.basicConfig(
    level=logging.DEBUG,
    filename='foo.log',
    filemode='w',
    format='%(asctime)s - %(levelname)s - %(message)s')

# parser = argparse.ArgumentParser(description="Foo")
parser = argparse_logger(description="Foo")
parser.add_argument('foo',type=int)
logging.debug("Start")

try:
    args = parser.parse_args(sys.argv[1:])
except:
    print("Error handling arguments")
    raise
logging.debug(f"Finish - {args.foo}")
print(f"Exiting! - {args.foo}")

This will show the following:

J:\>python arg_parse_log.py 5
Exiting! - 5

J:\>more foo.log
2018-02-07 11:34:45,647 - DEBUG - Start
2018-02-07 11:34:45,648 - DEBUG - Finish - 5

J:\>python arg_parse_log.py
usage: arg_parse_log.py [-h] foo
arg_parse_log.py: error: the following arguments are required: foo
Error handling arguments

J:\>more foo.log
2018-02-07 11:34:54,577 - DEBUG - Start
2018-02-07 11:34:54,578 - ERROR - the following arguments are required: foo



回答2:


I found a workaround that I don't believe is very good. But it seems to be working:

import argparse
import logging
import sys
import traceback

class argparse_logger(argparse.ArgumentParser):
    def _print_message(self, message, file=None):
        if file is sys.stderr:
            logger.error('Arg Parse did something bad...see below:')
            logger.error(message)
        else:
            super()._print_message(message,file=file)

def log_uncaught_exceptions(ex_cls, ex, tb):
    logging.critical(''.join(traceback.format_tb(tb)))
    logging.critical('{0}: {1}'.format(ex_cls, ex))

logging.basicConfig(
    level=logging.DEBUG,
    filename='foo.log',
    filemode='w',
    format='%(asctime)s - %(levelname)s - %(message)s')

# logging.getLogger('root')
logger = logging.getLogger('root')

sys.excepthook = log_uncaught_exceptions

logger.debug('This is a typical debug line')

parser = argparse_logger(description='Foo String')
parser.add_argument('foo',type=int)
args = parser.parse_args()
logger.debug('Input was %i'%(args.foo))


来源:https://stackoverflow.com/questions/48633847/python-argparse-errors-to-file

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!