在Python扩展中管理日志/警告 [英] Managing logs/warnings in Python extensions

查看:106
本文介绍了在Python扩展中管理日志/警告的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

TL; DR版本::如何在Python项目的C ++位内部使用可配置(最好是捕获)日志记录?详细信息如下.

TL;DR version: What do you use for configurable (and preferably captured) logging inside your C++ bits in a Python project? Details follow.

假设您有几个已编译的.so模块,可能需要进行一些错误检查并警告用户(部分)不正确的数据.目前,我正在使用一个非常简单的设置,即使用Python代码中的logging框架和C/C ++中的log4cxx库. log4cxx日志级别是在文件(log4cxx.properties)中定义的,目前已修复,我正在考虑如何使其更加灵活.我看到的几个选择:

Say you have a a few compiled .so modules that may need to do some error checking and warn user of (partially) incorrect data. Currently I'm having a pretty simplistic setup where I'm using logging framework from Python code and log4cxx library from C/C++. log4cxx log level is defined in a file (log4cxx.properties) and is currently fixed and I'm thinking how to make it more flexible. Couple of choices that I see:

  1. 控制它的一种方法是进行模块范围的配置调用.

  1. One way to control it would be to have a module-wide configuration call.

# foo/__init__.py
import sys
from _foo import import bar, baz, configure_log
configure_log(sys.stdout, WARNING)

# tests/test_foo.py
def test_foo():
    # Maybe a custom context to change the logfile for 
    # the module and restore it at the end.
    with CaptureLog(foo) as log:
        assert foo.bar() == 5
        assert log.read() == "124.24 - foo - INFO - Bar returning 5"

  • 每个执行日志记录的已编译函数都接受可选的日志参数.

  • Have every compiled function that does logging accept optional log parameters.

    # foo.c
    int bar(PyObject* x, PyObject* logfile, PyObject* loglevel) {
        LoggerPtr logger = default_logger("foo");
        if (logfile != Py_None)
            logger = file_logger(logfile, loglevel);
        ...
    }
    
    # tests/test_foo.py
    def test_foo():
        with TemporaryFile() as logfile:
            assert foo.bar(logfile=logfile, loglevel=DEBUG) == 5
            assert logfile.read() == "124.24 - foo - INFO - Bar returning 5"
    

  • 另一些​​方式?

  • Some other way?

    第二个似乎比较干净,但是它需要更改函数签名(或使用kwargs并对其进行解析).第一个可能有点尴尬,但是一口气设置了整个模块,并从每个单独的功能中删除了逻辑.

    Second one seems to be somewhat cleaner, but it requires function signature alteration (or using kwargs and parsing them). First one is.. probably somewhat awkward but sets up entire module in one go and removes logic from each individual function.

    您对此有何看法?我也都想办法替代解决方案.

    What are your thoughts on this? I'm all ears to alternative solutions as well.

    谢谢

    推荐答案

    我坚信Python中要完成尽可能多的工作,而只剩下必须在C语言中完成的工作.所以,我喜欢#2比#1更好,但是您是对的,它会使您所有的函数签名变得混乱.

    I'm a big believer in having as much work happen in Python as possible, leaving only the work that has to happen in C in C. So I like #2 better than #1, but you are right, it clutters up all your function signatures.

    我将创建一个模块级对象来处理日志记录,有点像回调. Python代码可以按其喜欢的任何方式创建对象,然后将其分配给模块对象. C代码可以简单地使用全局对象进行日志记录:

    I'd create a module-level object to handle the logging, sort of like a callback. The Python code could create the object any way it likes, then assign it to the module object. The C code can simply use the global object to do its logging:

    # Python:
    
    import my_compiled_module
    
    def log_it(level, msg):
        print "%s: Oh, look: %s" % (level, msg)
    
    my_compiled_module.logger = log_it
    
    # C
    
    static void log_it(unsigned int level, char * msg)
    {
        PyObject * args = Py_BuildValue("(Is)", level, msg);
        PyObject_Call(log_it, args, NULL);
        Py_DECREF(args);
    }
    

    现在,您可以在整个代码中简单地调用C log_it函数,而不必担心Python代码是如何完成的.当然,您的Python log_it函数将比此函数丰富,它将使您将所有日志记录集成到一个Python记录器中.

    Now you can simply call the C log_it function throughout your code, and not worry about how the Python code gets it done. Of course, your Python log_it function would be richer than this one, and it would let you get all of your logging integrated into one Python logger.

    这篇关于在Python扩展中管理日志/警告的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

  • 查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆