问题:
在进行UI自动化时,想要输出每次查找元素的日志,引入logging模块,并设置logging.INFO,但是实际上运行正常,但控制台并没有输出日志:

class BasePage:
    _driver = None
    _params={}
    _base_url = ""
    logging.basicConfig(level=logging.INFO)
    def __init__(self,driver:WebDriver = None):
        if driver is None:
            # 和瀏覽器打開的調試端口進行通信,瀏覽器要使用 --remote-debugging-port=9222 開啟調試
            chrome_options = Options()
            chrome_options.debugger_address = "127.0.0.1:9222"
            self._driver = webdriver.Chrome(options=chrome_options)
            self._driver.maximize_window()
            self._driver.implicitly_wait(3)
        else:
            self._driver = driver
        if self._base_url != "":
            self._driver.get(self._base_url)
    @handlie_blacklist
    def find(self,by,locator):
        # 调用find函数即打印日志
        logging.info(f"find:{locator}")
        if by == None:
            result=self._driver.find_element(*locator)
        else:
            result = self._driver.find_element(by,locator)
        return result

解决思路:
反复检查这段代码无误后,只能深入 logging.basicConfig 函数看看这个 python 自带的日志配置函数究竟做了什么(截取一部分)

def basicConfig(**kwargs):
    _acquireLock()
    try:
        if len(root.handlers) == 0:
            handlers = kwargs.pop("handlers", None)
            if handlers is None:
                if "stream" in kwargs and "filename" in kwargs:
                    raise ValueError("'stream' and 'filename' should not be "
                                     "specified together")
            else:
                if "stream" in kwargs or "filename" in kwargs:
                    raise ValueError("'stream' or 'filename' should not be "
                                     "specified together with 'handlers'")
            if handlers is None:
                filename = kwargs.pop("filename", None)
                mode = kwargs.pop("filemode", 'a')
                if filename:
                    h = FileHandler(filename, mode)
                else:
                    stream = kwargs.pop("stream", None)
                    h = StreamHandler(stream)
                handlers = [h]
            dfs = kwargs.pop("datefmt", None)
            style = kwargs.pop("style", '%')
            if style not in _STYLES:
                raise ValueError('Style must be one of: %s' % ','.join(
                                 _STYLES.keys()))
            fs = kwargs.pop("format", _STYLES[style][1])
            fmt = Formatter(fs, dfs, style)
            for h in handlers:
                if h.formatter is None:
                    h.setFormatter(fmt)
                root.addHandler(h)

分析这段程序,有个if语句判断 root.handlers 为空,则会运行后续代码给将每个 handler 添加到根 logger 的逻辑。推测root.handlers 不为空。
看下这个函数basicConfig()说明部分

Do basic configuration for the logging system. This function does nothing if the root logger already has handlers configured. It is a convenience method intended for use by simple scripts to do one-shot configuration of the logging package. The default behaviour is to create a StreamHandler which writes to sys.stderr, set a formatter using the BASIC_FORMAT format string, and add the handler to the root logger. A number of optional keyword arguments may be specified, which can alter the default behaviour.

渣道翻译:

对日志系统进行基本配置。
如果根日志记录器已经有处理程序,则此函数不执行任何操作配置。它是一种便于简单脚本使用的方法对日志包进行一次性配置。
默认行为是创建一个写入的StreamHandler。使用BASIC_FORMAT格式字符串设置格式化程序,以及将处理程序添加到根日志记录器。
可以指定许多可选关键字参数,这些参数可以更改默认的行为。

即在图1代码调用logging.basicConfig前已经调用了一次basicConfig,导致设置失效,其实还是使用系统默认的日志文件,根记录器始终默认为警告级别
打个断点验证下:
在这里插入图片描述
说明:
在调用logging.basicConfig前打印了root处理器的handles是有两个的,但是进一步去追踪是哪个地方先行调用了basicConfig,目前我还没有头绪,若有方法,望告知。

解决:
logging.basicConfig前清理已有 handlers

root_logger = logging.getLogger()
    for h in root_logger.handlers[:]:
        root_logger.removeHandler(h)
    logging.basicConfig(level=logging.INFO)

注意:不要写成for h in root_logger.handlers:

再次执行代码,控制台就正常输出日志了,完事收工!
在这里插入图片描述
参考帖子:
追踪方法很好:python logging 模块配置咋不起作用了?
其他logging相关知识:
python中logging日志模块详解
Python日志输出——logging模块
干货:
Python中内置的日志模块logging用法详解
python logging 替代print 输出内容到控制台和重定向到文件

# log.Log_Info('nihaohaohao') # 设置log的存储文件 logging.basicConfig(filename = os.path.join(os.getcwd(), 'logs/report_log.txt'), level = logging.DEBUG) logging.info('可以了吗嗷嗷嗷!') 原来是在调用logging.basicConfi 2.代码实例 import logging '''format=%(asctime)s具体时间 %(filename)s文件名 %(lenvelname)s日志等级 %(message)s具体信息 logging.basicConfig(level=logging.INFO, format='%(asctime)s %(filename)s %(levelname)s %(message)s', 说到日志,无论是开发写代码还是写UI自动化测试,都离不开日志的记录,它能给我们在定位问题、缺陷时带来很大的方便。通常测试人员使用最多的方法就是用print来打印出日志和报错信息,但是对于一些项目比较大的项目,使用print就不是那么方便了。因为print打印出来的日志没有时间,不知道日志记录的位置,针对这种情况,我们可以使用python自带的logging模块,可以很好地解决上面问题。... logging 模块是 Python 内置的标准模块,主要用于输出运行日志,可以设置输出日志的等级、日志保存路径、日志文件回滚等;相比 print,具备如下优点: 可以通过设置不同的日志等级,在 release 版本中只输出重要信息,而不必显示大量的调试信息; print 将所有信息都输出到标准输出中,严重影响开发者从标准输出中查看其它数据;logging 则可以由开发者决定将信息输出到什么地方,以及怎么输出; 和 print 相比,logging 是线程安全的。 参考文献:参考文章 生成文件名与指定日志 在这个示例中,我们将日志级别设置为 INFO,表示只记录 INFO 级别及以上的日志信息,输出格式设置为 %(asctime)s %(levelname)s %(message)s,表示在每条日志记录中包括时间戳、日志级别和日志消息。除了 basicConfig 方法,logging 模块还提供了很多其他的配置和使用方法,例如可以将日志输出到文件中,可以在日志记录中包含调用栈信息等。在这个示例中,我们使用 basicConfig 方法设置了日志级别为 DEBUG,并记录了不同级别的日志信息。 logging.info('info') logging.warning('出错了') logging.error('error message') logging.critical('critical message') 默认日志级别设置为WARNING... logging.basicConfig(level=logging.INFO, format='levelname:%(levelname)s filename: %(filename)s ' 'outputNumber:... # 日志信息配置 logging.basicConfig(level=logging.INFO, # 输出到日志文件中的日志级别 filename='mylog.log', # 日志文件名称 为什么要用logging模块在实际应用中,日志文件十分重要,通过日志文件,我们知道程序运行的细节;同时,当程序出问题时,我们也可以通过日志快速定位问题所在。在我们写程序时,也可以借助logging模块的输出信息来调试代码。但是很多人还是在程序中使用print()函数来输出一些信息,比如:print 这样用的话缺点很明显,当程序写好运行时,我们要把这些print()函数删掉,在简单的的程序中用还行,... ​ 橙好科技logging模块教程 文章目录1-logging介绍2-日志作用3-日志配置basicConfig3-日志级别level4-日志格式format4-输出日志到控制台5-输出日志到文件6-输出日志到控制台和文件7-骚操作 1-logging介绍 [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-pvNqUq0s-1620