로깅 인스턴스화에 대한 Python 평가 순서입니다. 가져온 모듈이 먼저 평가되는 이유는 무엇입니까? (Python order of evaluation for a logging instantiation. Why do imported modules get evaluated first?)


문제 설명

로깅 인스턴스화에 대한 Python 평가 순서입니다. 가져온 모듈이 먼저 평가되는 이유는 무엇입니까? (Python order of evaluation for a logging instantiation. Why do imported modules get evaluated first?)

안녕하세요 고급 질문이 있습니다. 나는 기본적으로 왜 다운스트림 클래스가 먼저 인스턴스화되는 클래스 속성 로그 객체를 가지고 있는지 어려움을 겪고 있습니다. 약 20개의 클래스와 3개의 다른 모듈이 있는 Python 응용 프로그램이 있고 응용 프로그램에서 일부 로깅을 수행합니다. cli에서 로깅 경로를 구성하고 싶지만 처음에는 로깅 경로를 하드 코딩하고 로깅 개체를 인스턴스화했습니다. 그런 다음 하드 코딩된 경로를 사용하여 애플리케이션의 다른 모든 부분에 인스턴스를 로깅합니다. 그래서 처음에는 로깅 경로를 하드 코딩했습니다(단지 app.log). 이제 사용자가 로깅 경로를 설정할 수 있도록 하려고 합니다. 그래서 내 Log 클래스에는 클래스 변수인 핸들러를 설정하는 싱글톤 방식의 메소드 set_handler가 있습니다. 한 번만 설정할 수 있다는 점에서 싱글톤 패턴을 따릅니다. 따라서 사용자는 "첫 번째" 매니저. 이후의 로그 인스턴스화를 위해 처리기가 이미 설정된 경우 처리기가 구성되지 않고 동일한 처리기가 사용되며 새 로그 개체만 반환됩니다. 따라서 사용자가 xyz.log를 전달하면 영원히 설정됩니다. 하지만 처음 실제로 호출될 때 정확히 알 수 없는 것 같습니다. 진입점은 로깅 개체가 처음 인스턴스화될 때와 많이 다릅니다. 로그 인스턴스화를 강제로 시도하고 있지만 파이썬은 첫 번째 인스턴스화를 계속 다른 것으로 유지합니다. 실제로 내가 먼저 실행하려는 클래스에서 가져온 가져온 클래스에서 가져오는 클래스입니다. 그리고 그 클래스(코드는 훨씬 나중까지 도달하지 않음)에는 먼저 인스턴스화되는 로그 개체가 있습니다. 그래서 그 클래스의 로그 객체가 인스턴스화되고 있지만 사용자가 제공한 로그 경로는 아직 전달되지 않았습니다. 이것이 제 의도입니다. 따라서 기본적으로 python이 적절한 로그 인스턴스화를 먼저 평가하도록 강제할 수 없습니다.


참조 솔루션

방법 1:

So what was happening was basically here, the logging object was being evaluated as soon as the class of the class attribute was imported. (When Class2 was imported, it's class attribute log was evaluated and thus instantiated). This guy did a blog about it ‑ https://chase‑seibert.github.io/blog/2012/01/20/python‑class‑attributes‑are‑evaluated‑on‑declaration.html. So to lay it out in more detail I had one file like

import other_stuff

from module2 import Class2

class Class1:
def init(self):
do stuff

def func1():
    do stuff with Class2 

</code></pre>

And then in module 2 it looked like

import os 
import subprocess 

import other_stuff 

class Class2:
    log = LoggerClass(log_path=__name__)

    def __init__(self):

    def func2():
        do stuff  

And in the application entry point it was like so. This was the part that I wanted to evaluate first... but it did not evaluate first.

import click 
import other_stuff 

from module1 import Class1

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

I was thinking that the log object in the start function in the entry point would be the first instantiated but it was the log object that was a class attribute of Class2 that was instantiated first actually. This is because a class's class attributes are evaluated upon being imported. Like when you import a class, that causes all the class attributes to be evaluated.

So I actually just changed the code in Class2 to be like

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

And then of course I change the statements that do the logging from Class2.log.logstuff() to Class2.log().logstuff(). So the calls to log stuff no longer reference the class attribute log and instead call the class method log().

(by uh_big_mike_boiuh_big_mike_boi)

참조 문서

  1. Python order of evaluation for a logging instantiation. Why do imported modules get evaluated first? (CC BY‑SA 2.5/3.0/4.0)

#Python #python-logging #python-3.x #logging






관련 질문

Python - 파일 이름에 특수 문자가 있는 파일의 이름을 바꿀 수 없습니다. (Python - Unable to rename a file with special characters in the file name)

구조화된 배열의 dtype을 변경하면 문자열 데이터가 0이 됩니다. (Changing dtype of structured array zeros out string data)

목록 목록의 효과적인 구현 (Effective implementation of list of lists)

for 루프를 중단하지 않고 if 문을 중지하고 다른 if에 영향을 줍니다. (Stop if statement without breaking for loop and affect other ifs)

기본 숫자를 10 ^ 9 이상으로 늘리면 코드가 작동하지 않습니다. (Code fails to work when i increase the base numbers to anything over 10 ^ 9)

사용자 지정 대화 상자 PyQT5를 닫고 데이터 가져오기 (Close and get data from a custom dialog PyQT5)

Enthought Canopy의 Python: csv 파일 조작 (Python in Enthought Canopy: manipulating csv files)

학생의 이름을 인쇄하려고 하는 것이 잘못된 것은 무엇입니까? (What is wrong with trying to print the name of the student?)

다단계 열 테이블에 부분합 열 추가 (Adding a subtotal column to a multilevel column table)

여러 함수의 변수를 다른 함수로 사용 (Use variables from multiple functions into another function)

리프 텐서의 값을 업데이트하는 적절한 방법은 무엇입니까(예: 경사하강법 업데이트 단계 중) (What's the proper way to update a leaf tensor's values (e.g. during the update step of gradient descent))

Boto3: 조직 단위의 AMI에 시작 권한을 추가하려고 하면 ParamValidationError가 발생합니다. (Boto3: trying to add launch permission to AMI for an organizational unit raises ParamValidationError)







코멘트