2013-04-08 10 views
15

टास्कपायथन: सभी मॉड्यूल भर में कस्टम प्रवेश

मैं स्क्रिप्ट का एक संग्रह है और मैं चाहें तो उसे वास्तविक संदेश प्रवेश करने कर मॉड्यूल के लिए कम से कम परिवर्तन के साथ एकीकृत प्रवेश संदेशों के उत्पादन के लिए।

मैंने एक छोटा मॉड्यूल 'custom_logger' लिखा है जिसे मैं मुख्य एप्लिकेशन से एक बार कॉल करने की योजना बना रहा हूं, क्या यह एक लॉगर लौटाएगा, जिसे मैं तब जारी रखूंगा।

submodules मैं एप्लिकेशन में आयात होगी ही (या बल्कि मैं उन्हें करना चाहते हैं) चाहिए

  • केवल "लॉग के रूप में आयात लॉगिंग" चाहिए - कि मेरी साइट के लिए विशिष्ट कुछ भी नहीं की आवश्यकता है बनाने के लिए तो अगर वे किसी और को उपयोगी पाते हैं तो वे सिर्फ दौड़ते हैं।
  • को केवल log.info/error('message 'के साथ संदेशों को लॉग इन करना चाहिए, उन्हें साइट-विशिष्ट कुछ भी जोड़ने के बिना
  • को पहले से कॉन्फ़िगर किए गए' रूट 'लॉगर का उपयोग अपने सभी स्वरूपण और हैंडरों के साथ करना चाहिए और रूट लॉगर को प्रभावित नहीं करना चाहिए विन्यास

* custom_logger.py *

import logging 
import logging.handlers 
import os 
import sys 


def getLogger(name='root', loglevel='INFO'): 
    logger = logging.getLogger(name) 

    # if logger 'name' already exists, return it to avoid logging duplicate 
    # messages by attaching multiple handlers of the same type 
    if logger.handlers: 
    return logger 
    # if logger 'name' does not already exist, create it and attach handlers 
    else: 
    # set logLevel to loglevel or to INFO if requested level is incorrect 
    loglevel = getattr(logging, loglevel.upper(), logging.INFO) 
    logger.setLevel(loglevel) 
    fmt = '%(asctime)s %(filename)-18s %(levelname)-8s: %(message)s' 
    fmt_date = '%Y-%m-%dT%T%Z' 
    formatter = logging.Formatter(fmt, fmt_date) 
    handler = logging.StreamHandler() 
    handler.setFormatter(formatter) 
    logger.addHandler(handler) 

    if logger.name == 'root': 
     logger.warning('Running: %s %s', 
        os.path.basename(sys.argv[0]), 
        ' '.join(sys.argv[1:])) 
    return logger 

फिर submodule जो है और क्या नहीं क्या काम करता है के उदाहरण के साथ कुछ परीक्षण संदेश हैं आता है।

submodule.py

import sys 
import custom_logger 
import logging 


class SubClass(object): 

    def __init__(self): 
    # NOK (no idea why since by default (no name parameter), it should return the root logger) 
    #log = logging.getLogger() 
    #log.info('message from SubClass/__init__') 

    # OK (works as expected) 
    #log = logging.getLogger('root') 
    #log.info('message from SubClass/__init__') 

    # OK (works as expected) 
    log = custom_logger.getLogger('root') 
    log.info('message from SubClass/__init__') 


    def SomeMethod(self): 
    # OK but I'd have to define `log` for every method, which is unacceptable 
    # Please see question below all code snippets 
    log = custom_logger.getLogger('root') 
    log.info('message from SubClass/SomeMethod') 

और मुख्य अनुप्रयोग: app.py यहां कुछ भी विशेष:

#!/usr/bin/python 

import custom_logger 
import submodule 

log = custom_logger.getLogger('root', loglevel='DEBUG') 

log.debug('debug message') 
log.info('info message') 
log.warning('warning message') 
log.error('error message') 

a = submodule.SubClass() # this should produce a log message 
a.SomeMethod()   # so should this 

आउटपुट है कि मैं के बाद और है कि मैं हो रही हूँ, बस एक बेहद बदसूरत तरीके से:

% ./app.py 
2013-04-08T03:07:46BST custom_logger.py WARNING : Running: app.py 
2013-04-08T03:07:46BST app.py    DEBUG : debug message 
2013-04-08T03:07:46BST app.py    INFO : info message 
2013-04-08T03:07:46BST app.py    WARNING : warning message 
2013-04-08T03:07:46BST app.py    ERROR : error message 
2013-04-08T03:07:46BST submodule.py  INFO : message from SubClass/__init__ 
2013-04-08T03:07:46BST submodule.py  INFO : message from SubClass/SomeMethod 

मैं app.py में एक लॉगर को परिभाषित करने में सक्षम होना चाहता हूं और फिर submodules में app.py में पहले से कॉन्फ़िगर किए गए लॉगर का उपयोग करने के लिए केवल मानक पायथन लॉगिंग लाइब्रेरी का उपयोग करना चाहता हूं।

इसके अलावा, एक बदसूरत वैकल्पिक हल: अगर मैं submodule.py में आयात के बाद नीचे दिए गए कोड को जगह:

log = custom_logger.getLogger('root') 

यह इससे पहले कि मेरे लकड़हारा app.py में कॉन्फ़िगर किया गया है, प्रभावी रूप से submodule बनाने निष्पादित किया जाएगा, मेरा ऐप लॉगिंग कॉन्फ़िगर नहीं करता है।

एक और वैकल्पिक हल मैं माना: उपवर्ग वर्ग के constuctor अंदर ही मैंने

self.log = custom_logger.getLogger('root')

को परिभाषित करने और उसके बाद self.log.error ('कुछ त्रुटि') इस्तेमाल कर सकते हैं। एक अच्छा तरीका होना चाहिए - अगर आप कुछ उपयोगी सुझाव दे सकते हैं या बता सकते हैं कि मैंने दस्तावेज़ को गलत समझा, तो मैं बहुत आभारी रहूंगा!

पीएस। मैंने पाइथन लॉगिंग को कितना पढ़ा है (मूल और उन्नत) और कुकबुक ताकि अगर मैंने वहां कुछ उपयोगी याद किया है, तो कृपया इसे इंगित करें।

धन्यवाद!

उत्तर

3

यदि आप रूट लॉगर को बदलना चाहते हैं तो आप बिना किसी तर्क के getLogger() का उपयोग कर सकते हैं।

केवल मुख्य मॉड्यूल में इंस्टेंस सेटअप के संबंध में, आप अपने लॉगर को तुरंत चालू कर सकते हैं, अपना स्वयं का हैंडलर जोड़ सकते हैं, और अन्य सभी submodules (जैसा कि मैंने किया था) में इसका उपयोग कर सकते हैं।

मैं custom_logger.py में एक वर्ग है कि StreamHandler विरासत में बनाया:

class MyHandler(logging.StreamHandler): 

    def __init__(self): 
     logging.StreamHandler.__init__(self) 
     fmt = '%(asctime)s %(filename)-18s %(levelname)-8s: %(message)s' 
     fmt_date = '%Y-%m-%dT%T%Z' 
     formatter = logging.Formatter(fmt, fmt_date) 
     self.setFormatter(formatter) 

फिर, submodule.py में, मैं getLogger आयात के बाद रख दिया और तरीकों में यह टिप्पणी की:

import sys 
import logging 

log = logging.getLogger('root') 

class SubClass(object): 

    def __init__(self): 
     log.info('message from SubClass/__init__') 

    def SomeMethod(self): 
     log.info('message from SubClass/SomeMethod') 

फिर, app.py में मैंने एक लॉगर इंस्टेंस बनाया (जो सभी मॉड्यूल में समान होगा) और मेरे हैंडलर को जोड़ा गया, जो आउटपुट स्वरूपित करता है:

#!/usr/bin/python 

import logging 
import custom_logger 
import submodule 

log = logging.getLogger('root') 
log.setLevel('DEBUG') 
log.addHandler(custom_logger.MyHandler()) 

log.debug('debug message') 
log.info('info message') 
log.warning('warning message') 
log.error('error message') 

a = submodule.SubClass() # this should produce a log message 
a.SomeMethod()   # so should this 

आउटपुट:

./app.py 
2013-04-08T15:20:05EEST app.py    DEBUG : debug message 
2013-04-08T15:20:05EEST app.py    INFO : info message 
2013-04-08T15:20:05EEST app.py    WARNING : warning message 
2013-04-08T15:20:05EEST app.py    ERROR : error message 
2013-04-08T15:20:05EEST submodule.py  INFO : message from SubClass/__init__ 
2013-04-08T15:20:05EEST submodule.py  INFO : message from SubClass/SomeMethod 
+0

धन्यवाद मिहाई। मैंने सोचा कि मुझे इसमें देखने के लिए और अधिक समय लगेगा लेकिन मुझे सप्ताहांत के लिए इंतजार करना होगा। अब तक मैं अपनी कक्षा बनाने में सक्षम हूं जो सब कुछ करता है (फॉर्मेटर्स, हैंडलर और सेटिंग loglevel संलग्न) submodule.py में getLogger ऑब्जेक्ट के रूप में लॉग को परिभाषित करके काम करता है। मैं उम्मीद कर रहा था कि यह कक्षा परिभाषा के बाहर चीजों को डाले बिना किया जा सकता है। मेरा प्रश्न अधिक था "मेरे द्वारा किए गए कुछ दृष्टिकोण क्यों अपेक्षित काम नहीं करते थे क्योंकि मैं इसके पीछे कारण समझना चाहता हूं, क्योंकि मुझे एक कोड सौंपने के विरोध में, लेकिन मैं आपकी मदद की सराहना करता हूं:) –

+0

मैंने अपना जवाब अपडेट किया। अन्यथा आप मॉड्यूल के कोड में देख सकते हैं। आप देख सकते हैं कि आयात के दौरान रूट लॉगर को तुरंत चालू किया जाता है। मुझे यह भी समझ में नहीं आता कि क्यों लॉगर ("रूट") एक ही काम नहीं करता है सभी परिस्थितियों में (आप app.py.py में getLogger() प्राप्त कर सकते हैं और submodule.py में getLogger ("root") प्राप्त कर सकते हैं और आपको जो चाहिए वह आपको मिलता है, लेकिन इसके विपरीत नहीं) – Mihai

+0

यह फ़ाइल पर stdout रीडायरेक्ट के साथ कैसे काम करें उदाहरण के लिए python ./app.py >> file.log? –

संबंधित मुद्दे