如何在Python中为argparse设置自定义输出处理程序?

时间:2015-04-29 05:44:16

标签: python python-2.7 logging argparse

我已将logger配置为在终端stdout和文件上打印,因此我可以拥有可以参考的日志消息存档。

通过向FileHandler对象添加logging可以轻松完成此操作。容易腻。

我现在想要完成的是当遇到解析错误时,使argparse同时记录到同一个文件以及日志到stdout。到目前为止它只打印到stdout。我查看了argparse documentation,但我无法找到有关为argparse设置不同输出流或管道的任何信息。

有可能吗?怎么样?

3 个答案:

答案 0 :(得分:6)

查看argparse.py source code似乎没有办法配置此行为。

我的建议是:

  • 使用补丁提交错误报告:)

覆盖/补丁:

  • print_*方法
  • error方法。

print_*方法似乎采用可选的file参数,默认为_sys.stdout

更新:或者您可以执行以下操作:在解析参数时临时重定向sys.stdout

from contextlib import contextmanager

@contextmanager
def redirect_stdout_stderr(stream):
    old_stdout = sys.stdout
    old_stderr = sys.stderr
    sys.stdout = stream
    sys.stderr = stream
    try:
        yield
    finally:
        sys.stdout = old_stdout
        sys.stderr = old_stderr


with redirct_stdout_stderr(logstream):
    args = parser.parse_args()

答案 1 :(得分:4)

似乎无法通过API执行此操作。

但是,您可以执行以下操作:

class LoggingArgumentParser(argparse.ArgumentParser):
    """Custom ArgumentPaarser that overrides _print_message"""

    def _print_message(self, message, file=None):
        if message:
            logger.write(message)

答案 2 :(得分:1)

虽然@James Mills给出的答案很好并且可以解决问题,但是在这种情况下不需要生成器。因此,收益是多余的。实现该目标的另一种方法(无需生成器)是编写自己的 context manager ,而无需使用内置的 contextlib.contextmanager 装饰器。如下所示。

class redirect_stdout_stderr(object):
    def __init__(self, stream):
        # Save the old std streams
        self.old_stream = sys.stdout
        self.old_error_stream = sys.stderr
        self.fstream = stream

    def __enter__(self):
        # Change the std streams to your streams when entering
        sys.stdout = self.fstream
        sys.stderr = self.fstream

    def __exit__(self, exc_type, exc_value, exc_traceback):
        # Change the std streams back to the original streams while exiting
        sys.stdout = self.old_stream
        sys.stderr = self.old_error_stream

根据您的情况,您可以执行以下操作。

with redirect_stdout_stderr(logstream):
    # __enter__() is executed
    args = parser.parse_args()
    # __exit__() is executed

希望这会有所帮助!