पायथन लॉगिंग - आयातित मॉड्यूल से लॉगिंग अक्षम करें


100

मैं पायथन लॉगिंग मॉड्यूल का उपयोग कर रहा हूं, और तीसरे पक्ष के मॉड्यूल द्वारा मुद्रित लॉग संदेशों को अक्षम करना चाहूंगा जिन्हें मैं आयात करता हूं। उदाहरण के लिए, मैं निम्नलिखित जैसे कुछ का उपयोग कर रहा हूं:

logger = logging.getLogger()
logger.setLevel(level=logging.DEBUG)
fh = logging.StreamHandler()
fh_formatter = logging.Formatter('%(asctime)s %(levelname)s %(lineno)d:%(filename)s(%(process)d) - %(message)s')
fh.setFormatter(fh_formatter)
logger.addHandler(fh)

जब मैं एक logger.debug ("मेरा संदेश!") करता हूं, तो यह मेरे डिबग संदेशों को प्रिंट करता है, लेकिन यह किसी भी मॉड्यूल से आयात किए गए डिबग संदेशों (जैसे अनुरोधों और कई अन्य चीजों) को भी प्रिंट करता है।

मैं उन मॉड्यूल से केवल लॉग संदेश देखना चाहता हूं, जिनमें मेरी रुचि है। क्या लॉगिंग मॉड्यूल ऐसा करना संभव है?

आदर्श रूप से, मैं लकड़हारे को "ModuleX, ModuleY" से संदेश प्रिंट करने और अन्य सभी को अनदेखा करने में सक्षम होना चाहूंगा।

मैंने निम्नलिखित को देखा, लेकिन मैं किसी कॉल को आयातित फ़ंक्शन में लॉगिंग से पहले अक्षम / सक्षम नहीं करना चाहता: लॉगिंग - आयातित मॉड्यूल लॉग को कैसे अनदेखा करें?

जवाबों:


69

समस्या यह है कि getLoggerतर्कों के बिना कॉल करने से रूट लकड़हारा वापस आ जाता है, इसलिए जब आप स्तर निर्धारित करते हैं तो आप logging.DEBUGउस मॉड्यूल का उपयोग करने वाले अन्य मॉड्यूल के लिए भी स्तर सेट कर रहे हैं।

आप इसे केवल रूट लॉगर का उपयोग करके हल कर सकते हैं । ऐसा करने के लिए बस एक नाम को तर्क के रूप में पास करें, उदाहरण के लिए आपके मॉड्यूल का नाम:

logger = logging.getLogger('my_module_name')
# as before

यह एक नया लकड़हारा पैदा करेगा और इस प्रकार यह अनजाने में अन्य मॉड्यूल के लिए लॉगिंग स्तर को बदल देगा।


स्पष्ट रूप से आपको इसका उपयोग logger.debugकरना होगा logging.debugक्योंकि उत्तरार्द्ध एक सुविधा फ़ंक्शन है debugजो रूट लॉगर की विधि को कॉल करता है ।

उन्नत लॉगिंग ट्यूटोरियल में इसका उल्लेख किया गया है । यह आपको यह भी पता करने की अनुमति देता है कि किस मॉड्यूल ने लॉग संदेश को सरल तरीके से ट्रिगर किया।


37
मैं __name__आर के साथ एक लकड़हारा बना रहा हूं लेकिन मैं अभी भी आयातित मॉड्यूल से लॉग देखता हूं। मैं एक ini कॉन्फ़िगरेशन फ़ाइल के साथ लॉगिंग कॉन्फ़िगर करने का प्रयास कर रहा हूं। मुझे इसके लिए क्या करना चाहिए?
दुर्गा स्वरूप

8
लकड़हारा पैदा करना __name__भी मेरे लिए काम नहीं आया। शायद इसलिए कि मैं एक स्टैंडअलोन स्क्रिप्ट का उपयोग कर रहा हूं और "मॉड्यूल" नहीं? मेरे लिए जो काम किया था वह आयातित मॉड्यूल ( matpplotlibमेरे मामले में) के माध्यम से logging.getLogger("matplotlib").setLevel(logging.WARNING)और मेरी स्क्रिप्ट के माध्यम से लॉगिंग के लिए कॉन्फ़िगर करना था logging.basicConfig
bli

1
मैं सिर्फ आपकी पंक्ति के मूल्य पर प्रकाश डालना चाहता था "जाहिर है कि आपको logger.debugइसके बजाय उपयोग करना होगा logging.debug"। यह का उपयोग कर बनाने के लिए एक आसान गलती है लॉगिंग के बजाय लकड़हारा लेकिन यह चतुर विन्यास आप सेट करना चाहते हैं के सभी usurps। मैंने इसे जीने के कुछ घंटे बिताए हैं!
समयदेव

@bli किसी लाइब्रेरी का विकास करते समय लॉगिंग के बीच एक बड़ा अंतर होता है जब एक निष्पादन योग्य विकसित करना। मूल रूप से: यदि आप एक मॉड्यूल / पैकेज लिख रहे हैं, जिसका अर्थ आयात करना है तो आपको कुछ भी कॉन्फ़िगर नहीं करना चाहिए । मॉड्यूल में केवल शामिल होना चाहिए logger = logging.getLogger('package.my_module')और आपका कॉल logger.debug/warning, लॉगिंग स्तर या हैंडलर का कोई कॉन्फ़िगरेशन नहीं हो सकता है । जब आप द्विआधारी आवेदन लिखने वहाँ आप विभिन्न लॉग और संचालकों के लिए स्तर तय करना चाहिए। लॉगिंग कॉन्फ़िगरेशन वाले लाइब्रेरी हमेशा एक समस्या होगी।
बाकुरू

मेरे मामले में, मैं जो पैकेज आयात करता हूं वह रूट लॉगर (थ्रू logging.info) का उपयोग करता है । क्या इस पैकेज से रूट लॉग को विशेष रूप से अक्षम करने का कोई तरीका है?
IANS

45

यदि आप अजगर loggingपैकेज का उपयोग करने जा रहे हैं , तो इसका उपयोग करने वाले प्रत्येक मॉड्यूल में लकड़हारे को परिभाषित करना एक सामान्य सम्मेलन है।

logger = logging.getLogger(__name__)

कई लोकप्रिय अजगर पैकेज ऐसा करते हैं, जिसमें शामिल हैं requests। यदि कोई पैकेज इस कन्वेंशन का उपयोग करता है, तो इसके लिए लॉगिंग को सक्षम / अक्षम करना आसान है, क्योंकि लॉगर नाम पैकेज के समान नाम होगा (या उस लकड़हारे का बच्चा होगा)। आप इसे अपने अन्य लॉगर्स के समान फ़ाइल में भी लॉग इन कर सकते हैं।

logger = logging.getLogger(__name__)
logger.setLevel(logging.DEBUG)

requests_logger = logging.getLogger('requests')
requests_logger.setLevel(logging.DEBUG)

handler = logging.StreamHandler()
handler.setLevel(logging.DEBUG)
logger.addHandler(handler)
requests_logger.addHandler(handler)

15
ध्यान रखें, कि जब आप अपने लॉगर को आधिकारिक बुनियादी ट्यूटोरियल में कॉन्फ़िगर करने का प्रयास करते हैं, जैसे logging.basicConfig(...)सभी लॉगर अब logging.lastResort( या पायथन 3.2 के साथ शुरू होता है), जो कोई हैंडलर नहीं दिया गया था या आपके द्वारा सेट किए गए हैंडलर के लिए आउटपुट होगा । इसलिए इसका उपयोग न करें या आप वैसे भी सभी लॉग संदेश प्राप्त करना जारी रखेंगे।
user136036

43

यकीन नहीं होता कि यह पोस्ट करना उचित है, लेकिन मैं लंबे समय से अटका हुआ था और किसी को भी इस मुद्दे पर मदद करना चाहता था, क्योंकि मुझे यह कहीं और नहीं मिला था!

मैं प्रवेश ट्यूटोरियल और समस्या निवारण लॉगिंग में बहुत सीधा प्रलेखन का पालन करने के बावजूद matplotlib से डिबग लॉग प्राप्त कर रहा था । मैं main()एक फ़ाइल में अपने लकड़हारे को आरंभ कर रहा था और दूसरी फ़ाइल से एक प्लॉट बनाने के लिए एक फ़ंक्शन आयात कर रहा था (जहां मैंने matplotibib आयात किया था)।

मेरे लिए काम करने से पहले इसे आयात करने से पहले मैटलोट्लिब का स्तर निर्धारित किया गया था , बजाय इसके कि मैं अपनी मुख्य फ़ाइल में अन्य मॉड्यूल के लिए था। यह मेरे लिए उल्टा लग रहा था, अगर किसी को इस बात की जानकारी है कि आप एक लकड़हारे के लिए कॉन्फिगरेशन कैसे सेट कर सकते हैं, जिसे अभी तक आयात नहीं किया गया है, तो मुझे यह जानने के लिए उत्सुक होना पड़ेगा कि यह कैसे काम करता है। धन्यवाद!

मेरी मुख्य फाइल में:

import logging
import requests
logger = logging.getLogger(__name__)
logger.setLevel(logging.DEBUG)
logging.getLogger('requests').setLevel(logging.DEBUG)

def main():
  ...

मेरी plot.pyफ़ाइल में:

import logging
logging.getLogger('matplotlib').setLevel(logging.WARNING)
import matplotlib.pyplot as plt

def generatePlot():
  ...

मुझे त्रुटि मिली: 'लकड़हारा' ऑब्जेक्ट में कोई विशेषता नहीं है 'DEBUG'। logger.DEBUGहोना चाहिएlogging.DEBUG
फॉक्सिरिस

धन्यवाद! यह वास्तव में मदद करता है! मैंने अपने मुख्य लॉगिंग कॉन्फ़िगरेशन के बाद और कमांड से पहले matplotlib लॉगिंग स्तर निर्धारित किया है जो matplotlib आयात करेगा। हल किया!
gph

मैंने मॉड्यूल को आयात matplotlibकरने के WARNING बाद लॉगिंग के लिए सेट कर दिया है, क्योंकि आयात करने से पहले इसे जोड़ना एक लिंट-त्रुटि देगा। यह अभी भी मेरे लिए काम करता है। matplotlib==3.3.2अगर यह मदद करता है मैं Python 3.7 में उपयोग कर रहा हूँ ।
एंड-

9

@Bakuriu काफी सुरुचिपूर्ण ढंग से कार्य की व्याख्या करता है। इसके विपरीत, आप getLogger()अवांछित लॉगर्स को पुनः प्राप्त करने और पुन: कॉन्फ़िगर / अक्षम करने के लिए विधि का उपयोग कर सकते हैं ।

मैं इस logging.fileConfig()पद्धति को भी जोड़ना चाहता था, जिसे एक पैरामीटर स्वीकार किया जाता है, disable_existing_loggersजिसे पहले से परिभाषित किसी भी लकड़हारे (यानी आयातित मॉड्यूल में) को निष्क्रिय कर दिया जाएगा।


9

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

logging.config.dictConfig({
    'version': 1,
    'disable_existing_loggers': True,
})

ध्यान दें कि आपको उन सभी मॉड्यूल को आयात करने की आवश्यकता है जिन्हें आप पहले लॉग इन नहीं करना चाहते हैं! अन्यथा उन लोगों को "मौजूदा लॉगर" नहीं माना जाएगा। यह तब उन मॉड्यूल से सभी लॉगर को अक्षम कर देगा। इससे आपको महत्वपूर्ण त्रुटियों का भी सामना करना पड़ सकता है!

कॉन्फ़िगरेशन के लिए संबंधित विकल्पों का उपयोग करने वाले अधिक विस्तृत उदाहरणों के लिए, https://gist.github.com/st4lk/6287746 देखें , और यहांcoloredlog लाइब्रेरी के साथ कॉन्फ़िगरेशन के लिए YAML का उपयोग करके एक (आंशिक रूप से काम कर रहा) उदाहरण है ।


आपका सवाल क्या हैं?
user1767754

1
यह requestउदाहरण के लिए काम करता है , लेकिन यह तब काम नहीं करेगा जब आयातित मॉड्यूल अपनी कक्षा के अंदर अपने लॉगर बनाते हैं जिसे आप बाद में कॉल करते हैं, जैसे APSchedulerआप कॉल करते हैं BackgroundScheduler.BackgroundScheduler()। एक समाधान के लिए यहां देखें: stackoverflow.com/a/48891485/2441026
user136036

यह मेरे मामले में yaml विन्यास फाइल के साथ काम करता है
user4015990

4

आप कुछ इस तरह का उपयोग कर सकते हैं:

logging.getLogger("imported_module").setLevel(logging.WARNING)
logging.getLogger("my_own_logger_name").setLevel(logging.DEBUG)

यह अपने ही मॉड्यूल के लॉग स्तर को DEBUG में सेट करेगा, जबकि आयातित मॉड्यूल को समान स्तर का उपयोग करने से रोकता है।

नोट: (उद्धरण के बिना) के "imported_module"साथ प्रतिस्थापित किया जा सकता है imported_module.__name__, और यदि आप इसे पसंद करना चाहते हैं, तो इसे "my_own_logger_name"प्रतिस्थापित किया जा सकता __name__है।


1

मुझे भी यही समस्या थी। मेरे पास एक logging_config.py फ़ाइल है जिसे मैं अन्य सभी py फ़ाइलों में आयात करता हूं। Logging_config.py फ़ाइल में मैंने रूट लॉगर लॉगिंग स्तर ERROR पर सेट किया है (डिफ़ॉल्ट रूप से इसकी चेतावनी):

logging.basicConfig(
    handlers=[
        RotatingFileHandler('logs.log',maxBytes=1000, backupCount=2),
        logging.StreamHandler(), #print to console
    ],
    level=logging.ERROR
)

अन्य मॉड्यूल में मैं logging_config.py आयात करता हूं और एक नया लकड़हारा घोषित करता हूं और इसके स्तर को डीबग करने के लिए सेट करता हूं:

log = logging.getLogger(__name__)
log.setLevel(logging.DEBUG)

इस तरह मैं अपनी py फाइलों में जो कुछ भी लॉग करता हूं वह लॉग होता है, लेकिन डिबग और इंफो लेवल पर आयातित सामान जैसे कि urllib, request, boto3 आदि से लॉग नहीं किया जाता है। अगर उन आयात मॉड्यूल में कुछ त्रुटि है, तो उसके लॉग, क्योंकि मैंने रूट लॉगर स्तर को ERROR पर सेट किया है।


0

एक और बात पर विचार करना लॉगर वर्ग की प्रचार संपत्ति है।

उदाहरण के लिए, साबुन कॉल से निपटने के लिए पाई-सूड्स लाइब्रेरी, यहां तक ​​कि ERROR के लिए भी

logging.getLogger('suds.client').setLevel(logging.ERROR)
logging.getLogger('suds.transport').setLevel(logging.ERROR)
logging.getLogger('suds.xsdschema').setLevel(logging.ERROR)
logging.getLogger('suds.wsdl').setLevel(logging.ERROR)

sxbasics.py नामक एक मॉड्यूल के बारे में लॉग्स लॉग की एक बड़ी राशि का सृजन करता है

यहाँ छवि विवरण दर्ज करें

क्योंकि लॉग का प्रचार डिफ़ॉल्ट रूप से सही है, गलत पर सेट करना, इसके बजाय, मैंने 514MB लॉग पुनर्प्राप्त किया।

import logging
logging.getLogger("suds").propagate = False
logging.getLogger('suds.client').setLevel(logging.ERROR)
logging.getLogger('suds.transport').setLevel(logging.ERROR)
logging.getLogger('suds.xsdschema').setLevel(logging.ERROR)
logging.getLogger('suds.wsdl').setLevel(logging.ERROR)
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.