python - যবহ - প্রোগ্রামিং এসেনশিয়ালস পাইথন ৩ pdf




একাধিক মডিউল মধ্যে পাইথন লগিং ব্যবহার করে (6)

আমার একটি ছোট পাইথন প্রকল্প রয়েছে যা নিম্নলিখিত কাঠামো আছে -

Project 
 -- pkg01
   -- test01.py
 -- pkg02
   -- test02.py
 -- logging.conf

আমি stdout এবং একটি লগ ফাইল বার্তা মুদ্রণ করতে ডিফল্ট লগিং মডিউল ব্যবহার করার পরিকল্পনা। লগিং মডিউল ব্যবহার করার জন্য, কিছু সূচনা প্রয়োজন -

import logging.config

logging.config.fileConfig('logging.conf')
logger = logging.getLogger('pyApp')

logger.info('testing')

বর্তমানে, আমি লগিং বার্তাগুলি শুরু করার আগে প্রতিটি মডিউলে এই সূচনাটি করি। এই প্রারম্ভিকটি একবারে একবার একবার করা সম্ভব যে এই প্রকল্পটি পুরো প্রকল্পের লগ-ইন করে পুনঃব্যবহার করা হয়?


@ ইয়ার্কির সমাধান ভাল লাগে। আমি এটি somemore যোগ করতে চান -

class Singleton(type):
    _instances = {}

    def __call__(cls, *args, **kwargs):
        if cls not in cls._instances.keys():
            cls._instances[cls] = super(Singleton, cls).__call__(*args, **kwargs)
        return cls._instances[cls]


class LoggerManager(object):
    __metaclass__ = Singleton

    _loggers = {}

    def __init__(self, *args, **kwargs):
        pass

    @staticmethod
    def getLogger(name=None):
        if not name:
            logging.basicConfig()
            return logging.getLogger()
        elif name not in LoggerManager._loggers.keys():
            logging.basicConfig()
            LoggerManager._loggers[name] = logging.getLogger(str(name))
        return LoggerManager._loggers[name]    


log=LoggerManager().getLogger("Hello")
log.setLevel(level=logging.DEBUG)

তাই LoggerManager সমগ্র অ্যাপ্লিকেশন একটি প্লাগযোগ্য হতে পারে। এটা ইন্দ্রিয় এবং মান তোলে আশা করি।


অন্য সমাধান মধ্যে নিক্ষেপ।

আমার মডিউল এর মূল init আমার কিছু আছে:

import logging

def get_module_logger(mod_name):
  logger = logging.getLogger(mod_name)
  handler = logging.StreamHandler()
  formatter = logging.Formatter(
        '%(asctime)s %(name)-12s %(levelname)-8s %(message)s')
  handler.setFormatter(formatter)
  logger.addHandler(handler)
  logger.setLevel(logging.DEBUG)
  return logger

তারপর প্রতিটি ক্লাসে আমার একটি লগার দরকার, আমি করি:

from [modname] import get_module_logger
logger = get_module_logger(__name__)

লগ মিস করা হয়, আপনি তাদের কাছ থেকে আসা মডিউল দ্বারা তাদের উৎস পার্থক্য করতে পারেন।


আমি সবসময় নীচের হিসাবে এটি করতে।

' log_conf.py ' নামক log_conf.py প্যাটার্ন হিসাবে আমার লগ কনফিগার করতে একটি একক পাইথন ফাইল ব্যবহার করুন।

#-*-coding:utf-8-*-

import logging.config

def singleton(cls):
    instances = {}
    def get_instance():
        if cls not in instances:
            instances[cls] = cls()
        return instances[cls]
    return get_instance()

@singleton
class Logger():
    def __init__(self):
        logging.config.fileConfig('logging.conf')
        self.logr = logging.getLogger('root')

অন্য মডিউল, শুধু কনফিগার আমদানি।

from log_conf import Logger

Logger.logr.info("Hello World")

এটি কেবলমাত্র এবং কার্যকরীভাবে লগ করার জন্য একটি সিঙ্গল্ট প্যাটার্ন।


এই উত্তরগুলির বেশিরভাগই আপনাকে একটি মডিউলের শীর্ষে প্রস্তাব করে

import logging
logger = logging.getLogger(__name__)

এটা আমার খুব বুদ্ধিমান অনুশীলন বলে মনে হয়। কারণ ফাইল কনফিগারেশন ডিফল্টরূপে বিদ্যমান বিদ্যমান সকল লগগারগুলিকে অক্ষম করবে। যেমন

#my_module
import logging

logger = logging.getLogger(__name__)

def foo():
    logger.info('Hi, foo')

class Bar(object):
    def bar(self):
        logger.info('Hi, bar')

এবং আপনার প্রধান মডিউল:

#main
import logging

# load my module - this now configures the logger
import my_module

# This will now disable the logger in my module by default, [see the docs][1] 
logging.config.fileConfig('logging.ini')

my_module.foo()
bar = my_module.Bar()
bar.bar()

এখন logging.ini তে উল্লিখিত লগ খালি হবে, কারণ বিদ্যমান লগগার ফাইল কনফিগার কল দ্বারা অক্ষম করা হয়েছে।

যদিও এটি প্রায়শই সম্ভব (disable_existing_loggers = মিথ্যা), আপনার লাইব্রেরির প্রকৃতপক্ষে অনেক ক্লায়েন্ট এই আচরণ সম্পর্কে জানেন না এবং আপনার লগগুলি পাবেন না। সর্বদা logging.get স্থানীয়ভাবে কলিং কল করে আপনার ক্লায়েন্টদের জন্য এটি সহজ করুন। হ্যাট টিপ: আমি ভিক্টর লিনের ওয়েবসাইট থেকে এই আচরণ সম্পর্কে শিখেছি।

তাই ভাল অনুশীলন পরিবর্তে সর্বদা logging.getLogger কল করতে হয়। যেমন

#my_module
import logging

logger = logging.getLogger(__name__)

def foo():
    logging.getLogger(__name__).info('Hi, foo')

class Bar(object):
    def bar(self):
        logging.getLogger(__name__).info('Hi, bar')    

এছাড়াও, যদি আপনি আপনার মূল্যে ফাইল কনফিগারেশন ব্যবহার করেন তবে disable_existing_loggers = মিথ্যা, আপনার লাইব্রেরী ডিজাইনার মডিউল স্তরের লগগারের উদাহরণগুলি ব্যবহার করে।


বিভিন্ন উত্তর আছে। আমি একটি অনুরূপ এখনো ভিন্ন সমাধান সঙ্গে শেষ পর্যন্ত যে আমাকে ইন্দ্রিয় তোলে, সম্ভবত এটি আপনার সাথে জ্ঞান করবে। আমার প্রধান উদ্দেশ্য তাদের স্তরের দ্বারা হ্যান্ডলারদের লগ (পাস করতে কনসোল, সতর্কতা এবং উপরের ডিবাগ স্তরের লগ) করতে সক্ষম হওয়া উচিত:

from flask import Flask
import logging
from logging.handlers import RotatingFileHandler

app = Flask(__name__)

# make default logger output everything to the console
logging.basicConfig(level=logging.DEBUG)

rotating_file_handler = RotatingFileHandler(filename="logs.log")
rotating_file_handler.setLevel(logging.INFO)

app.logger.addHandler(rotating_file_handler)

logger.py নামক একটি চমৎকার ব্যবহার ফাইল তৈরি করেছেন:

import logging

def get_logger(name):
    return logging.getLogger("flask.app." + name)

flask.app ফ্লাস্ক একটি hardcoded মান। অ্যাপ্লিকেশন লগার সবসময় তার মডিউল এর নাম হিসাবে flask.app দিয়ে শুরু হয়।

এখন, প্রতিটি মডিউলে, আমি নিম্নলিখিত মোডে এটি ব্যবহার করতে সক্ষম হচ্ছি:

from logger import get_logger
logger = get_logger(__name__)

logger.info("new log")

এটি সর্বনিম্ন প্রচেষ্টার সাথে "app.flask.MODULE_NAME" এর জন্য একটি নতুন লগ তৈরি করবে।


সর্বোত্তম অনুশীলন প্রতিটি মডিউলে, যেমন একটি সংজ্ঞায়িত লগার আছে:

import logging
logger = logging.getLogger(__name__)

মডিউল শীর্ষের কাছাকাছি, এবং তারপর মডিউল অন্যান্য কোড যেমন উদাহরণ

logger.debug('My message with %s', 'variable data')

যদি আপনি একটি মডিউল ভিতরে লগিং কার্যকলাপ সাবডিভাইভ প্রয়োজন, উদাহরণ ব্যবহার করুন

loggerA = logging.getLogger(__name__ + '.A')
loggerB = logging.getLogger(__name__ + '.B')

এবং loggerA এবং loggerB loggerA লগ ইন করুন।

আপনার প্রধান প্রোগ্রাম বা প্রোগ্রামে, উদাহরণস্বরূপ:

def main():
    "your program code"

if __name__ == '__main__':
    import logging.config
    logging.config.fileConfig('/path/to/logging.conf')
    main()

অথবা

def main():
    import logging.config
    logging.config.fileConfig('/path/to/logging.conf')
    # your program code

if __name__ == '__main__':
    main()

একাধিক মডিউল থেকে লগিংয়ের জন্য here দেখুন এবং here কোডের জন্য কনফিগারেশন লগিংয়ের জন্য যা অন্য কোড দ্বারা লাইব্রেরী মডিউল হিসাবে ব্যবহার করা হবে।

আপডেট: fileConfig() কল করার সময়, আপনি fileConfig() disable_existing_loggers=False fileConfig() নির্দিষ্ট করতে চাইলে আপনি পাইথন 2.6 বা তার পরে ব্যবহার করছেন (আরও তথ্যের জন্য ডক্স দেখুন)। পূর্বনির্ধারিত মান পশ্চাদপট সামঞ্জস্যের জন্য True , যা সমস্ত বিদ্যমান fileConfig() দ্বারা নিষ্ক্রিয় করা হবে না যতক্ষণ না তারা বা তাদের পূর্বপুরুষের কনফিগারেশনে স্পষ্টভাবে নাম দেওয়া হয়। মান False সেট থাকা অবস্থায়, বিদ্যমান লগগারগুলি একা চলে যায়। পাইথন 2.7 / পাইথন 3.2 বা dictConfig() করার পরে, আপনি dictConfig() API বিবেচনা করতে পারেন যা fileConfig() চেয়ে ভাল, কারণ এটি কনফিগারেশনে আরও নিয়ন্ত্রণ দেয়।







config