একাধিক মডিউলে লগিং ব্যবহার করা


257

আমার একটি অজগর প্রকল্প রয়েছে যার নীচের কাঠামো রয়েছে -

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

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

import logging.config

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

logger.info('testing')

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


3
আমার উত্তরে আপনার মন্তব্যের জবাবে: fileConfigলগিং করা প্রতিটি মডিউলে আপনাকে কল করতে হবে না , যদি না আপনি if __name__ == '__main__'সমস্তটিতে যুক্তি না রেখে থাকেন। প্যাকেজটি একটি লাইব্রেরি হলে প্রোস্টের উত্তরটি অনুশীলন করা ভাল নয়, যদিও এটি আপনার পক্ষে কাজ করে - একটি যুক্ত করা ছাড়া লাইব্রেরি প্যাকেজে লগিং কনফিগার করা উচিত নয় NullHandler
বিনয় সাজিপ

1
প্রোস্ট সূচিত করেছে যে আমাদের প্রতিটি মডিউলে আমদানি এবং লগার স্টেম্ট কল করতে হবে এবং কেবলমাত্র মডিউলটিতে ফাইলকনফিগ স্টেমটি কল করতে হবে। আপনি কি বলছেন এর সাথে মিল নেই?
কোয়েস্ট Monger

6
প্রোস্ট বলছে যে আপনার লগিং কনফিগারেশন কোডটি প্রবেশ করা উচিত package/__init__.py। এটি আপনার if __name__ == '__main__'কোড রাখার জায়গাটি সাধারণত নয় । এছাড়াও, প্রোস্টের উদাহরণ দেখে মনে হচ্ছে এটি কনফিগার কোডটিকে আমদানিতে নিঃশর্তভাবে কল করবে, যা আমার কাছে ঠিক দেখাচ্ছে না। সাধারণত, লগিং কনফিগার কোডটি এক জায়গায় করা উচিত এবং আপনি যখন____ আমদানি করবেন তখন ব্যতীত আমদানির পার্শ্ব-প্রতিক্রিয়া হিসাবে ঘটবে না।
বিনয় সাজিপ

আপনি ঠিক বলেছেন, আমি তার কোডের নমুনায় '# প্যাকেজ / __ init__.py' লাইনটি পুরোপুরি মিস করেছি। যে বিন্দু এবং আপনার ধৈর্য জন্য ধন্যবাদ।
কোয়েস্ট Monger

1
তাহলে একাধিক হলে কী হয় if __name__ == '__main__'? (এটি যদি হয় তবে তা স্পষ্টভাবে উল্লেখ করা হয়নি)
kon psych

উত্তর:


293

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

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যথাযথ হিসাবে।

আপনার মূল প্রোগ্রাম বা প্রোগ্রামগুলিতে, উদাহরণস্বরূপ করুন:

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()

দেখুন এখানে একাধিক মডিউল থেকে লগ-ইন জন্য, এবং এখানে যা অন্যান্য কোড দ্বারা একটি লাইব্রেরি মডিউল রূপে ব্যবহৃত হবে কোডের জন্য লগিং কনফিগারেশনের জন্য।

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


21
আপনি যদি আমার উদাহরণটি দেখুন, আমি ইতিমধ্যে আপনি যা পরামর্শ দিয়েছেন তা করছি। আমার প্রশ্নটি ছিল আমি কীভাবে এই লগিং সূচনাটিকে কেন্দ্রীভূত করব যে আমাকে এই 3 টি বিবৃতি পুনরাবৃত্তি করতে হবে না। এছাড়াও, আপনার উদাহরণে আপনি 'logging.config.fileConfig (' logging.conf ')' stmt মিস করেছেন। এই stmt আসলে আমার উদ্বেগের মূল কারণ। আপনি দেখতে পাচ্ছেন, আমি যদি প্রতিটি মডিউলে লগারটি শুরু করি, আমাকে প্রতিটি মডিউলে এই স্ট্যাম্টটি টাইপ করতে হবে। তার অর্থ প্রতিটি মডিউলে কনফ ফাইলের পথ সন্ধান করা হবে, যা আমার কাছে সেরা অনুশীলনের মতো মনে হয় না (মডিউল / প্যাকেজের অবস্থানগুলি পরিবর্তন করার সময় বিপর্যয় কল্পনা করুন)।
কোয়েস্ট Monger

4
আপনি যদি লগার তৈরি করার পরে ফাইলকনফিগ কল করেন তবে একই বা অন্য কোনও মডিউলে (যেমন আপনি যখন ফাইলের শীর্ষে লগার তৈরি করেন) কাজ করে না। লগিং কনফিগারেশন কেবল পরে তৈরি লগারগুলিতে প্রয়োগ হয়। সুতরাং এই পদ্ধতির কাজ করে না বা একাধিক মডিউলগুলির জন্য একটি কার্যকর বিকল্প নয়। @ কোয়েস্ট মনিজার: আপনি সর্বদা অন্য ফাইলটি তৈরি করতে পারেন যা কনফিগার ফাইলটির অবস্থান ধারণ করে ..;)
ভিনসেন্ট কেটেলারস

2
@ অক্সিডেটর: অগত্যা নয় - disable_existing_loggersপতাকাটি দেখুন যা Trueপূর্বনির্ধারিত তবে সেট করা যেতে পারে False
বিনয় সাজিপ

1
@ বিনয় সজিপ, আপনাকে ধন্যবাদ মডিউলগুলিতে কিন্তু ক্লাসের বাইরেও কাজ করে এমন লগারদের জন্য আপনার কাছে কি সুপারিশ রয়েছে? যেহেতু মূল ফাংশন বলার আগে আমদানি করা হয়, সেই লগগুলি ইতিমধ্যে লগ হয়ে গেছে। আমার অনুমানটি মূল মডিউলে সমস্ত আমদানির একমাত্র উপায় হওয়ার আগে আপনার লগারটি সেট আপ করা হবে? আপনি যদি চান তবে এই লগারটি মূলত ওভাররাইট করা যেতে পারে।
ভিনসেন্ট কেটেলারস

1
আমি যদি আমার সমস্ত মডিউল নির্দিষ্ট লগারের ডিফল্ট সতর্কতা থেকে লগিং স্তর আলাদা করতে চাই, তবে প্রতিটি মডিউলটিতে আমাকে সেটিংটি করতে হবে? বলুন, আমি আমার সমস্ত মডিউল INFO এ লগ করতে চাই।
রাজ

127

প্রকৃতপক্ষে প্রতিটি লগার পিতা-মাতার প্যাকেজ লগার (যার অর্থ package.subpackage.moduleকনফিগারেশন উত্তরাধিকার সূত্রে প্রাপ্ত হয়) এর সন্তান package.subpackage), সুতরাং আপনাকে কেবলমাত্র রুট লগারটি কনফিগার করতে হবে This এটি logging.config.fileConfig(লগারের জন্য আপনার নিজস্ব কনফিগারেশন) বা logging.basicConfig(রুট লগার সেট করে ) দ্বারা অর্জন করা যেতে পারে । আপনার এন্ট্রি মডিউল সেটআপ লগিং ( __main__.pyবা যাই হোক না কেন আপনি চালাতে, উদাহরণস্বরূপ চান main_script.py__init__.pyপাশাপাশি কাজ করে)

বেসিক কনফিগ ব্যবহার:

# package/__main__.py
import logging
import sys

logging.basicConfig(stream=sys.stdout, level=logging.INFO)

ফাইল কনফিগ ব্যবহার করে:

# package/__main__.py
import logging
import logging.config

logging.config.fileConfig('logging.conf')

এবং তারপরে প্রতিটি লগার তৈরি করে:

# package/submodule.py
# or
# package/subpackage/submodule.py
import logging
log = logging.getLogger(__name__)

log.info("Hello logging!")

আরও তথ্যের জন্য অ্যাডভান্সড লগিং টিউটোরিয়াল দেখুন


15
এটি এখন পর্যন্ত, সমস্যার সহজ সমাধান, এটির উল্লেখ না করে মডিউলগুলির মধ্যে পিতামাতা-সন্তানের সম্পর্ককে উদ্ভাসিত করে এবং এই বিষয়টি সম্পর্কে আমি অবহিত ছিলাম না le danke।
কোয়েস্ট Monger

তুমি ঠিক. এবং হিসাবে বিনয় তার পোস্টে উল্লেখ, আপনার সমাধান তার নেই ডান যেমন দীর্ঘ Init .py মডিউল। যখন আমি এটিকে মূল মডিউলটিতে (প্রবেশের পয়েন্ট) প্রয়োগ করি তখন আপনার সমাধান কাজ করে।
কোয়েস্ট Monger

2
প্রশ্নটি পৃথক মডিউলগুলির সাথে সম্পর্কিত হওয়ায় আসলে আরও অনেক প্রাসঙ্গিক উত্তর।
জান সিলা

1
বোবা প্রশ্ন সম্ভবত: যদি লগ-ইন না থাকে __main__.py(যেমন আমি কোনও স্ক্রিপ্টে মডিউলটি ব্যবহার করতে চাই যার লগার নেই) logging.getLogger(__name__)তখনও মডিউলে কিছু প্রকারের লগিং করতে হবে বা এটি ব্যতিক্রম বাড়াবে?
বিল

1
অবশেষে। আমার একটি ওয়ার্কিং লগার ছিল, তবে উইন্ডোজটিতে প্যাটারাল রান করার জন্য জবলিব দিয়ে ব্যর্থ হয়েছিল। আমি অনুমান করি এটি সিস্টেমে ম্যানুয়াল টুইঙ্ক - সমান্তরালে অন্য কিছু ভুল is কিন্তু, এটি অবশ্যই কাজ করে! ধন্যবাদ
বি ফুর্তাদো

17

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

আমার লগকে সিঙ্গলটন প্যাটার্ন হিসাবে কনফিগার করতে একটি একক পাইথন ফাইল ব্যবহার করুন যার নাম ' 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")

এটি সহজ এবং দক্ষতার সাথে লগ করার জন্য একক প্যাটার্ন।


1
সিঙ্গলটন প্যাটার্ন বিশদ দেওয়ার জন্য ধন্যবাদ। আমি এটি বাস্তবায়নের পরিকল্পনা করছিলাম তবে তারপরে @ প্রকল্প সমাধানটি আরও সহজ এবং আমার প্রয়োজনগুলি পুরোপুরি ফিট করে। তবে আমি দেখতে পাচ্ছি যে আপনার সমাধানটি কার্যকর হচ্ছে এমন বড় প্রকল্পগুলি যেগুলির একাধিক পয়েন্ট রয়েছে (মূল বাদে)। danke।
কোয়েস্ট Monger

46
এটি অকেজো। রুট লগার ইতিমধ্যে একটি সিঙ্গলটন। Logger.logr.info এর পরিবর্তে কেবল logging.info ব্যবহার করুন।
পোড

9

এর মধ্যে বেশ কয়েকটি উত্তর প্রস্তাব দেয় যে আপনি যে মডিউলটি করছেন তার শীর্ষে

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()

এখন লগিং.ইএনআই-তে উল্লিখিত লগটি ফাঁকা থাকবে, কারণ বিদ্যমান লগারটি ফাইলকনফিগ কল দ্বারা অক্ষম করা হয়েছিল।

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

সুতরাং ভাল অনুশীলন হ'ল সর্বদা স্থানীয়ভাবে লগিং.গেটলগার কল করা। যেমন

#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')    

এছাড়াও, যদি আপনি আপনার প্রধানতে ফাইলকনফিগ ব্যবহার করেন তবে অক্ষম_অস্তিত্ব_লগারগুলি = মিথ্যা সেট করুন, আপনার লাইব্রেরি ডিজাইনাররা মডিউল স্তরের লগার উদাহরণগুলি ব্যবহার করেন।


আপনি চালাতে পারবেন না? logging.config.fileConfig('logging.ini') আগেimport my_module ? যেমন এই উত্তরে পরামর্শ দেওয়া হয়েছে
lucid_dreamer

নিশ্চিত নয় - তবে সেভাবে আমদানি এবং এক্সিকিউটেবল কোডের মিশ্রণটি অবশ্যই খারাপ অভ্যাস হিসাবে বিবেচিত হবে। আপনি চান না যে আপনার ক্লায়েন্টরা তাদের আমদানির আগে লগিং কনফিগার করতে হবে কিনা তা খতিয়ে দেখা উচিত, বিশেষত যখন একটি তুচ্ছ বিকল্প থাকে! কল্পনা করুন যদি অনুরোধগুলির মতো একটি বহুল ব্যবহৃত লাইব্রেরি যদি তা করে থাকে ....!
phil_20686

"নিশ্চিত নয় - তবে সেভাবে আমদানি এবং সম্পাদনযোগ্য কোডের মিশ্রণটি অবশ্যই খারাপ অভ্যাস হিসাবে বিবেচিত হবে।" - কেন?
lucid_dreamer

কেন এটি খারাপ তা নিয়ে আমি খুব একটা পরিষ্কার নই। এবং আমি আপনার উদাহরণটি পুরোপুরি বুঝতে পারি না। আপনি কি এই উদাহরণের জন্য আপনার কনফিগারেশন পোস্ট করতে পারেন এবং কিছু ব্যবহার দেখাতে পারেন?
lucid_dreamer

1
আপনি অফিসিয়াল ডক্সের বিরোধিতা করছেন বলে মনে হচ্ছে : 'লগার নামকরণ করার সময় ব্যবহার করার জন্য একটি ভাল কনভেনশন হ'ল প্রতিটি মডিউলে লগিং ব্যবহার করা হয় যা নিম্নরূপে নামকরণ করা হয়: logger = logging.getLogger(__name__)'
আয়রন 9

8

আমার জন্য একাধিক মডিউলগুলিতে লগইন লাইব্রেরির একটি উদাহরণ ব্যবহার করার একটি সহজ উপায় হ'ল সমাধানটি নিম্নলিখিত:

base_logger.py

import logging

logger = logging
logger.basicConfig(format='%(asctime)s - %(message)s', level=logging.INFO)

অন্যান্য ফাইল

from base_logger import logger

if __name__ == '__main__':
    logger.info("This is an info message")

7

অন্য সমাধানে নিক্ষেপ করা হচ্ছে।

আমার মডিউলটির init .py এ আমার মতো কিছু রয়েছে:

# mymodule/__init__.py
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

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

# mymodule/foo.py
from [modname] import get_module_logger
logger = get_module_logger(__name__)

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


"আমার মডিউলটির মূল সূচনা" বলতে কী বোঝায়? এবং "তারপরে প্রতিটি ক্লাসে আমার একটি লগার দরকার, আমি করি:"? আপনি কি_মডিউল.পি নামে একটি নমুনা এবং মডিউল কলার_মডিউল.পি থেকে আমদানি হিসাবে এর ব্যবহারের একটি উদাহরণ সরবরাহ করতে পারেন? আমি যে ফর্ম্যাটটির বিষয়ে জিজ্ঞাসা করছি তার অনুপ্রেরণার জন্য এই উত্তরটি দেখুন । পৃষ্ঠপোষকতা করার চেষ্টা করছেন না। আমি আপনার উত্তরটি বোঝার চেষ্টা করছি এবং আমি জানি আপনি যদি এটি সেভাবে লিখে থাকেন তবে আমি চাই।
lucid_dreamer

1
@ lucid_dreamer আমি পরিষ্কার করে দিয়েছি।
টমি

4

আপনিও এরকম কিছু নিয়ে আসতে পারেন!

def get_logger(name=None):
    default = "__app__"
    formatter = logging.Formatter('%(levelname)s: %(asctime)s %(funcName)s(%(lineno)d) -- %(message)s',
                              datefmt='%Y-%m-%d %H:%M:%S')
    log_map = {"__app__": "app.log", "__basic_log__": "file1.log", "__advance_log__": "file2.log"}
    if name:
        logger = logging.getLogger(name)
    else:
        logger = logging.getLogger(default)
    fh = logging.FileHandler(log_map[name])
    fh.setFormatter(formatter)
    logger.addHandler(fh)
    logger.setLevel(logging.DEBUG)
    return logger

এখন আপনি একই মডিউলে এবং পুরো প্রকল্প জুড়ে একাধিক লগার ব্যবহার করতে পারেন যদি উপরেরটি একটি পৃথক মডিউলে সংজ্ঞায়িত করা হয় এবং অন্যান্য মডিউলগুলিতে আমদানি করা লগিংয়ের প্রয়োজন হয়।

a=get_logger("__app___")
b=get_logger("__basic_log__")
a.info("Starting logging!")
b.debug("Debug Mode")

4

@ ইয়ার্কির সমাধানটি আরও ভাল মনে হয়েছিল। আমি এটিতে আরও যুক্ত করতে চাই -

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)

সুতরাং লোগার ম্যানেজার পুরো অ্যাপ্লিকেশনে প্লাগযোগ্য হতে পারে। আশা করি এটি বোধগম্য এবং মূল্যবান হবে।


11
লগিং মডিউলটি ইতিমধ্যে সিলেটলেটগুলির সাথে কাজ করে। logging.getLogger ("হ্যালো") আপনার সমস্ত মডিউল জুড়ে একই লগার পাবেন।
পোড

2

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

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)

লগার.পি নামে একটি দুর্দান্ত ইউটি ফাইল তৈরি করেছে:

import logging

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

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

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

from logger import get_logger
logger = get_logger(__name__)

logger.info("new log")

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


2

সর্বোত্তম অনুশীলনটি হ'ল আলাদাভাবে একটি মডিউল তৈরি করা যার কেবলমাত্র একটি পদ্ধতি রয়েছে যার কাজটি আমরা কলিং পদ্ধতিতে লগার হ্যান্ডলারটি দেই। এই ফাইলটিকে m_logger.py হিসাবে সংরক্ষণ করুন

import logger, logging

def getlogger():
    # logger
    logger = logging.getLogger(__name__)
    logger.setLevel(logging.DEBUG)
    # create console handler and set level to debug
    #ch = logging.StreamHandler()
    ch = logging.FileHandler(r'log.txt')
    ch.setLevel(logging.DEBUG)
    # create formatter
    formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s')
    # add formatter to ch
    ch.setFormatter(formatter)
    # add ch to logger
    logger.addHandler(ch)
    return logger

যখনই লগার হ্যান্ডলারের প্রয়োজন হয় এখন getlogger () পদ্ধতিটি কল করুন।

from m_logger import getlogger
logger = getlogger()
logger.info('My mssg')

1
আপনার কোনও অতিরিক্ত পরামিতি না থাকলে এটি ভাল good তবে, যদি ধরা যাক, --debugঅ্যাপটিতে আপনার বিকল্প রয়েছে এবং এই প্যারামিটারের ভিত্তিতে আপনার অ্যাপ্লিকেশনটিতে সমস্ত লগারে লগিং স্তরটি সেট করতে চান ...
দ্য গডফাদার

@ দ্য গডফাদার হ্যাঁ এই পদ্ধতির মাধ্যমে এটি অর্জন করা শক্ত। আমরা এই পরিস্থিতিতে যা করতে পারি তা হ'ল একটি শ্রেণি তৈরি করা যার জন্য অবজেক্ট তৈরির সময় প্যারামিটার হিসাবে ফর্ম্যাটর লাগবে এবং লগার হ্যান্ডেলটি ফেরত দেওয়ার অনুরূপ ফাংশন থাকবে this এ সম্পর্কে আপনার মতামত কী?
মৌসুম সিং

হ্যাঁ, আমি অনুরূপ কাজটি করেছি, get_logger(level=logging.INFO)একরকম একক সিঙ্গলটনকে ফিরিয়ে আনার জন্য তৈরি করেছি , সুতরাং যখন এটি মূল অ্যাপ্লিকেশন থেকে প্রথমবারের মতো কল করা হয়, এটি লগার এবং হ্যান্ডলারগুলিকে যথাযথ স্তরের সূচনা করে এবং তারপরে একই loggerজিনিসটিকে অন্য সমস্ত পদ্ধতিতে ফিরিয়ে দেয় ।
গডফাদার

0

অজগর থেকে নতুন তাই আমি জানিনা এটির পরামর্শ দেওয়া হয় কিনা তবে এটি বয়লারপ্লেট পুনরায় না লেখার জন্য দুর্দান্ত কাজ করে।

আপনার প্রকল্প একটি থাকতে হবে Init .py তাই এটি একটি মডিউল রূপে লোড করা যাবে

# Put this in your module's __init__.py
import logging.config
import sys

# I used this dictionary test, you would put:
# logging.config.fileConfig('logging.conf')
# The "" entry in loggers is the root logger, tutorials always 
# use "root" but I can't get that to work
logging.config.dictConfig({
    "version": 1,
    "formatters": {
        "default": {
            "format": "%(asctime)s %(levelname)s %(name)s %(message)s"
        },
    },
    "handlers": {
        "console": {
            "level": 'DEBUG',
            "class": "logging.StreamHandler",
            "stream": "ext://sys.stdout"
        }
    },
    "loggers": {
        "": {
            "level": "DEBUG",
            "handlers": ["console"]
        }
    }
})

def logger():
    # Get the name from the caller of this function
    return logging.getLogger(sys._getframe(1).f_globals['__name__'])

sys._getframe(1)পরামর্শ থেকে আসে এখানে

তারপরে অন্য কোনও ফাইলে আপনার লগারটি ব্যবহার করতে:

from [your module name here] import logger

logger().debug("FOOOOOOOOO!!!")

আদেশ সহকারে:

  1. আপনাকে অবশ্যই ফাইলগুলি মডিউল হিসাবে চালাতে import [your module]হবে , অন্যথায় এটি কাজ করবে না:
    • python -m [your module name].[your filename without .py]
  2. আপনার প্রোগ্রামের এন্ট্রি পয়েন্টের জন্য লগারের নাম হবে __main__, তবে যে কোনও সমাধান ব্যবহারের __name__ক্ষেত্রে সেই সমস্যাটি থাকবে।
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.