2011-05-12 12 views
33

Dahili logging'u kullanan basit bir Python betiğim var.Python - İşlevler arasında logger referansını geçmekten kaçının mı?

Bir işlevin içine giriş yapmayı yapıyorum.

#!/usr/bin/env python 
import logging 
import ... 

def configure_logging(): 
    logger = logging.getLogger("my logger") 
    logger.setLevel(logging.DEBUG) 
    # Format for our loglines 
    formatter = logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s") 
    # Setup console logging 
    ch = logging.StreamHandler() 
    ch.setLevel(logging.DEBUG) 
    ch.setFormatter(formatter) 
    logger.addHandler(ch) 
    # Setup file logging as well 
    fh = logging.FileHandler(LOG_FILENAME) 
    fh.setLevel(logging.DEBUG) 
    fh.setFormatter(formatter) 
    logger.addHandler(fh) 
    return logger 

def count_parrots(): 
    ... 
    logger.debug?? 

if __name__ == '__main__': 
    logger = configure_logging() 
    logger.debug("I'm a log file") 
    parrots = count_parrots() 

içimde __main__ gelen logger cezası çağırabilir: Temel yapısı böyle bir şey olurdu. Ancak, count_parrots() işlevinin içinden logger'ı nasıl ararım? Böyle bir kaydediciyi yapılandırmanın en pythonik yolu nedir?

cevap

32

Kök (varsayılan) kaydediciyi kullanabilir ve böylece modül seviyesi logging.debug, ... işlevlerini kullanabilir veya kaydedicinizi kullanarak işlevini alabilirsiniz. Gerçekten de, getLogger işlevi, bir kayıt defteri (fabrika gibi) ile fabrika benzeri bir işlevdir, yani, her zaman verilen günlük adı için aynı örneği döndürür. Böylece basitçe başında

logger = logging.getLogger("my logger") 

kullanarak count_parrots içinde arşivleyiciyi alabilirsiniz. Ancak, sözleşmeniz, logger'ınız için noktalı bir hiyerarşik isim kullanmaktır. Örneğin, bireysel fonksiyonlara günlüğü davranışı eklemek için bir dekoratör kullanabilirsiniz

:

def debug(loggername): 
    logger = logging.getLogger(loggername) 
    def log_(enter_message, exit_message=None): 
     def wrapper(f): 
      def wrapped(*args, **kargs): 
       logger.debug(enter_message) 
       r = f(*args, **kargs) 
       if exit_message: 
        logger.debug(exit_message) 
       return r 
      return wrapped 
     return wrapper 
    return log_ 

my_debug = debug('my.logger') 

@my_debug('enter foo', 'exit foo') 
def foo(a, b): 
    return a+b 

sen logger adı "hardcode" ve üst yada kubbe kaldırmak http://docs.python.org/library/logging.html#logging.getLogger

DÜZENLEME bakın seviye kapanışı ve my_debug.

+5

Tamam, böylece loging.getLogger öğesini, günlüğe kaydetmesi gereken her işlevin başında arayabilirim. Kesinlikle savurgan ve tekrarlayan görünüyor? Yeterince adil. Ya da nesne yönelimli olmaktan daha mı iyi olur ve bütün sınıfı bir sınıfa çekmeye çalışır mıyım? (Bildiğim çok genel bir soru, sadece Python dünyasında işin ne olduğunu araştırıyorum). – victorhooi

+0

İşlevinizi logger değişkenini örnek değişkeni olarak atayabilir veya (tercih ettiğim) günlük işlevlerini tek tek işlevlerinize eklemek için bir dekoratör oluşturabilirsiniz –

+9

Bu yanıt Python 'günlüğe kaydetme işleminin yanlış olduğunu hemen hemen gösterir. modül ... – rkrzr

-3

loggercount_parrots() için bağımsız değişken olarak verebilirsiniz Veya ne yapardım, sınıf papağanı oluşturur ve yöntemini logger olarak kullanır.

6

Günlüğe kaydetmeyi işlemenin tipik yolu, bir genel değişkende depolanan bir modül başına günlüğe kaydediciye sahip olmaktır. Bu modüldeki herhangi bir işlev ve yöntem daha sonra aynı logger örneğine başvurur.

Bu

belgelerinde avans günlüğü öğretici intro kısaca ele alınmıştır: http://docs.python.org/howto/logging.html#advanced-logging-tutorial

Sen can geçişli kaydedicisi parametreleri olarak etrafında örnekleri, ancak bunu yaparken genellikle nadirdir.

+0

Standart uygulamanın logger = logging.getLogger ("logger.name") kullanmak olduğunu sanıyordum. –

+0

Modül düzeyinde, elbette. Aynı modülde farklı işlevler ve yöntemler için ayrı kaydedicilerin kullanılması genellikle aşırı sıklıkta gerçekleşir. Bir istisna, ayrı kaydedicilerin kullanılması, hangi konuların belirli olayları kaydettiğini kaydetmek için çok kolay bir yol olabilir. – ncoghlan

+0

Ah. Aslında 'global' anahtar sözcüğünü kullanmayı kastettiğini sanmıştım. –

13

Sen tıpkı yapabilirsiniz:

logger = logging.getLogger("my logger") 

sizin count_parrots() yönteminde. Daha önce kullanılan adı (yani "günlüğüm") ilettiğinizde, günlüğe kaydetme modülü bu isme karşılık gelen aynı örneği döndürür.

Güncelleme: logging tutorial (emphais madeninde) Gönderen

getLogger() değilse bir o sağlanırsa belirtilen adla bir logger örneğine başvuru veya kök döndürür. Adlar, periyotlu hiyerarşik yapılardır.Aynı adı ile getLogger() öğesinin birden çok adı, aynı logger nesnesine bir başvuru döndürecektir.

0

Python içinde nasıl çalıştığını küresel değişkenler tarafından karıştı. Bir işlev içinde, logger = logging.getLogger("my logger") gibi bir şey yapıyor olsaydınız ve global logger'u değiştirmeyi umuyorsanız, yalnızca global logger bildirmeniz gerekir.

Örneğinizi değiştirmek için, dosyanın başlangıcında bir global günlük kaydı nesnesi oluşturabilirsiniz. Modülünüz başka bir tane tarafından alınabiliyorsa, NullHandler'u eklemeniz gerekir, böylece kitaplığın içe aktarıcısı etkinleştirme işlemini etkinleştirmezse, lib'unuzla (ref) ilgili herhangi bir sorun yoktur.

#!/usr/bin/env python 
import logging 
import ... 

logger = logging.getLogger("my logger").addHandler(logging.NullHandler()) 

def configure_logging(): 
    logger.setLevel(logging.DEBUG) 
    # Format for our loglines 
    formatter = logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s") 
    # Setup console logging 
    ch = logging.StreamHandler() 
    ch.setLevel(logging.DEBUG) 
    ch.setFormatter(formatter) 
    logger.addHandler(ch) 
    # Setup file logging as well 
    fh = logging.FileHandler(LOG_FILENAME) 
    fh.setLevel(logging.DEBUG) 
    fh.setFormatter(formatter) 
    logger.addHandler(fh) 

def count_parrots(): 
    ... 
    logger.debug('counting parrots') 
    ... 
    return parrots 

if __name__ == '__main__': 
    configure_logging() 
    logger.debug("I'm a log file") 
    parrots = count_parrots() 
İlgili konular