簡體   English   中英

Python:使用數據類字段參數啟動記錄器

[英]Python: initiated Logger with dataclass field param

這是我的Logger class:

import logging
import os
import datetime


class Logger:
    _logger = None

    def __new__(cls, user: str, *args, **kwargs):
        if cls._logger is None:
            cls._logger = super().__new__(cls, *args, **kwargs)
            cls._logger = logging.getLogger("crumbs")
            cls._logger.setLevel(logging.DEBUG)
            formatter = logging.Formatter('[%(asctime)s] [%(levelname)s] [%(filename)s] [%(funcName)s] [%(lineno)d]: %(message)s')
            now = datetime.datetime.now()
            directory_name = f'./log/{now.strftime("%Y-%m-%d")}'
            base_log_name = f'/{user}'
            log_file_extension = '.log'
            if not os.path.isdir(directory_name):
                os.mkdir(directory_name)
            file_handler = logging.FileHandler(f'{directory_name}{base_log_name}{now.strftime("%d-%m-%Y")}{log_file_extension}', 'w', 'utf-8')
            stream_handler = logging.StreamHandler()
            file_handler.setFormatter(formatter)
            stream_handler.setFormatter(formatter)
            cls._logger.addHandler(file_handler)
            cls._logger.addHandler(stream_handler)
        return cls._logger

這是我的class接受用戶argument ,我希望我的log文件在file name中使用我的用戶名創建:

@dataclass(kw_only=True)
class RunningJobManager:
    user: str = field(init=True)
    password: str = field(init=True)
    logging: Logger = field(init=False, default_factory=Logger(user=user))

所以目前我在Logger class 中的用戶field的類型是dataclasses.Field而不是string 我也嘗試使用default_factorydefault instread

我得到了這個錯誤:

Curerenly 我的代碼因 OSError,[Errno 22] 無效參數而崩潰:'G:\my_project\log\2023-01-20\Field(name=None,type=None,default=<dataclasses._MISSING_TYPE object at 0x0000017B1E78DB10>,default_factory = <dataclasses._missing_type object at 0x0000017b1e78db110>,init = true,repr = true,repr = note,sumh = none,compare = true,metadata = metadata = mappingproxy(} -01-2023.log'

在這一行:

file_handler = logging.FileHandler(f'{directory_name}{base_log_name}{now.strftime("%d-%m-%Y")}{log_file_extension}', 'w', 'utf-8')

這不是數據類根據其他字段處理字段初始化的方式。 fielddefault_factory參數應該是一個零參數的 callable 標准庫文檔指出:

default_factory:如果提供,它必須是一個零參數可調用函數,當此字段需要默認值時將被調用...

換句話說,不可能將任何參數傳遞給default_factory

使用其他字段的值初始化字段的正確方法是使用__post_install__方法:

@dataclass(kw_only=True)
class RunningJobManager:
    user: str = field(init=True)
    password: str = field(init=True)
    logging: Logger = field(init=False, default=None)

    def __post_init__(self):
        if self.logging is None:
            self.logging = Logger(self.user)

這是dictConfig的示例:

import logging
import os
from dataclasses import dataclass, field
from logging import Logger
from logging.config import dictConfig


@dataclass(kw_only=True)
class AbstractJobManager:
    user: str = field(init=True)

    @property
    def logger(self) -> Logger:
        return logging.getLogger('crumbs')

    def __post_init__(self):
        if not os.path.isdir('log'):
            os.mkdir('log')

        # some config from YAML, TOML or hardcoded - doesn't matter...
        config = {
            'version': 1,
            'loggers': {
                'crumbs': {
                    'level': 'INFO',
                    'handlers': ['file_handler'],
                },
            },
            'handlers': {
                'file_handler': {
                    'level': 'INFO',
                    'class': 'logging.handlers.RotatingFileHandler',
                    'filename': f'./log/{self.user}.log',  # I skipped %Y-%m-%d...
                    'backupCount': 3,
                    'formatter': 'simple',
                },
            },
            'formatters': {
                'simple': {
                    'format': '%(pathname)s:%(lineno)d %(asctime)s - %(levelname)s - %(message)s',
                },
            },
        }

        dictConfig(config)


@dataclass(kw_only=True)
class RunningJobManager(AbstractJobManager):
    password: str = field(init=True)

    def run(self):
        self.logger.info('user = %s, password = %s', self.user, self.password)


RunningJobManager(user='falukky', password='Hello World!').run()
RunningJobManager(user='ridley', password='scott').run()
RunningJobManager(user='jimi', password='hendrix').run()

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM