0

嗨,我有一个高级问题。我基本上很难理解为什么下游类首先实例化了一个类属性日志对象。我有一个包含大约 20 个类和 3 个不同模块的 python 应用程序,并且该应用程序进行了一些日志记录。我想从 cli 配置日志记录路径,但起初,我只是硬编码了日志记录路径并实例化了一个日志记录对象。然后使用硬编码路径将该日志实例记录到应用程序的所有其他部分。所以我一开始就硬编码了日志记录路径(只是app.log)。现在我试图允许用户设置日志记录的路径。所以在我的Log课堂上,我有一个单例式的方法set_handler设置处理程序,它是一个类变量。它遵循单例模式,因为它只能设置一次。因此,用户还将为“第一个”处理程序传递一个日志记录路径。如果已经为以后的日志实例设置了处理程序,则没有配置处理程序,使用相同的处理程序,只返回一个新的日志对象。因此,如果用户通过,xyz.log那么它将被永久设置,很好。但似乎我无法确定第一次时间实际上它被称为。入口点与第一次实例化日志对象时大不相同。我试图强制日志实例化,但 python 一直将第一个实例化为不同的东西。它实际上是一个由导入的类导入的类,该类由我实际要首先执行的类导入。并且那个类(代码直到很久以后才遇到)有一个日志对象,它首先被实例化。所以该类的日志对象正在被实例化,但用户提供的日志路径尚未通过,这是我的意图。所以基本上我不能强迫python首先评估正确的日志实例。

4

1 回答 1

0

所以发生的事情基本上就在这里,只要类属性的类被导入,日志对象就会被评估。(当Class2被导入时,它的类属性log被评估并因此被实例化)。这个人写了一篇关于它的博客 - https://chase-seibert.github.io/blog/2012/01/20/python-class-attributes-are-evaluated-on-declaration.html。因此,为了更详细地列出它,我有一个文件,例如

import other_stuff   
 
from module2 import Class2 

class Class1:
    def __init__(self):
            do stuff 
    
    def func1():
        do stuff with Class2 

然后在模块 2 中看起来像

import os 
import subprocess 

import other_stuff 

class Class2:
    log = LoggerClass(log_path=__name__)
      
    def __init__(self):

    def func2():
        do stuff  

在应用程序入口点中就是这样。这是我想首先评估的部分……但它没有首先评估。

import click 
import other_stuff 

from module1 import Class1

@click.command("start")
@click.option(--logpath)
def start(logpath):
    log = LoggerClass(log_path=__name__)

我在想入口点log中函数中的对象start将是第一个实例化的,但实际上首先实例化的log是作为类属性的对象Class2。这是因为类的类属性是在导入时评估的。就像您导入一个类时,这会导致评估所有类属性。

所以我实际上只是将 Class2 中的代码更改为

import os 
import subprocess 

import other_stuff 

class Class2:
    log = None
      
    def __init__(self):

    def func2():
        do stuff 

    @classmethod
    def log(cls):
        if cls.log is None:
             cls.log = LoggerClass(log_name=__name__)
        return cls.log

然后当然我将执行日志记录的语句从 更改Class2.log.logstuff()Class2.log().logstuff(). 因此,对日志内容的调用不再引用类属性log,而是调用类方法log()

于 2021-07-19T02:05:21.383 回答