पायथन लॉगर बनाना लॉग फ़ाइल के अतिरिक्त सभी संदेशों को आउटपुट करना है


450

क्या पायथन बनाने का एक तरीका है loggingमॉड्यूल का उपयोग करके स्वचालित रूप से आउटपुट चीज़ों को लॉग फ़ाइल के अलावा स्टडआउट करने के लिए जहां उन्हें जाना चाहिए? उदाहरण के लिए, मैं करने के लिए सभी कॉल करना चाहते हैं logger.warning, logger.critical, logger.errorअपने इच्छित स्थानों पर जाने के लिए, लेकिन इसके अलावा में हमेशा में कॉपी किया stdout। यह संदेशों की नकल करने से बचने के लिए है:

mylogger.critical("something failed")
print "something failed"

1
कृपया इस उत्तर की जाँच करें stackoverflow.com/questions/9321741/…
SeF

जवाबों:


635

सभी लॉगिंग आउटपुट हैंडलर्स द्वारा संभाला जाता है; बस logging.StreamHandler()रूट लकड़हारे में जोड़ें ।

यहां एक स्ट्रीम हैंडलर कॉन्फ़िगर करना ( stdoutडिफ़ॉल्ट के बजाय का उपयोग करना stderr) और इसे रूट लकड़हारा से जोड़ना है:

import logging
import sys

root = logging.getLogger()
root.setLevel(logging.DEBUG)

handler = logging.StreamHandler(sys.stdout)
handler.setLevel(logging.DEBUG)
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
handler.setFormatter(formatter)
root.addHandler(handler)

4
यह ठीक है, लेकिन अगर यह पहले से ही एक फ़ाइल पर रीडायरेक्ट हो गया है तो मुझे stdoutइसके अलावा कैसे प्रिंट किया जा सकता है ?

54
@ user248237: सचित्र के रूप में एक नया हैंडलर जोड़कर । नए हैंडलर मौजूदा हैंडलर को प्रतिस्थापित नहीं करते हैं, वे लॉग प्रविष्टियों को संसाधित करने के लिए भी मिलते हैं।
मार्टिन पीटर्स

@MartijnPieters क्या हर लॉग स्टेटमेंट को प्रिंट करने के लिए एक स्ट्रिंग जोड़ने का एक तरीका है?
प्रखर मोहन श्रीवास्तव

7
@PrakharMohanSrivastava मुझे लगता है कि आप इसे स्ट्रिंग में जोड़ सकते हैं logging.Formatter

3
@ himanshu219: उपयोग मामला यह है कि जैसे ही आप कई हैंडलर जोड़ना शुरू करते हैं, आप आमतौर पर अंतर करना चाहते हैं। डीबग कंसोल, चेतावनी के लिए और ऊपर एक फ़ाइल, आदि के लिए
मार्टिन पीटर्स

505

Stdout में लॉग इन करने का सबसे सरल तरीका:

import logging
import sys
logging.basicConfig(stream=sys.stdout, level=logging.DEBUG)

57
हम्म, लेकिन यह एक फ़ाइल में लॉग इन नहीं है, है ना? सवाल यह था कि फाइल करने और सांत्वना देने के लिए लॉगिंग कैसे की जाए ।
वेडेनरिंड


पायथन 3 में कम से कम, ऐसा लग रहा है कि stream=sys.stdoutअभी भी मेरे लिए कंसोल पर लॉगिंग के लिए काम करना बाकी है।
टेलर एड्मिस्टन

3
@TaylorEdmiston हाँ, लेकिन यह stderr स्ट्रीम AFAIK है। शेल से आउटपुट पुनर्निर्देशित करने का प्रयास करें।
सोरिन

1
ठीक। यह दोनों का उत्तर नहीं देता है: फ़ाइल में प्रवेश करना और सांत्वना देना, लेकिन यह जानना अच्छा था कि मुझे 3 लाइनों या उससे कम में क्या चाहिए।
स्टीव 3 पी 0 19

67

कई हैंडलर का उपयोग करना संभव है।

import logging
import auxiliary_module

# create logger with 'spam_application'
log = logging.getLogger('spam_application')
log.setLevel(logging.DEBUG)

# create formatter and add it to the handlers
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')

# create file handler which logs even debug messages
fh = logging.FileHandler('spam.log')
fh.setLevel(logging.DEBUG)
fh.setFormatter(formatter)
log.addHandler(fh)

# create console handler with a higher log level
ch = logging.StreamHandler()
ch.setLevel(logging.ERROR)
ch.setFormatter(formatter)
log.addHandler(ch)

log.info('creating an instance of auxiliary_module.Auxiliary')
a = auxiliary_module.Auxiliary()
log.info('created an instance of auxiliary_module.Auxiliary')

log.info('calling auxiliary_module.Auxiliary.do_something')
a.do_something()
log.info('finished auxiliary_module.Auxiliary.do_something')

log.info('calling auxiliary_module.some_function()')
auxiliary_module.some_function()
log.info('done with auxiliary_module.some_function()')

# remember to close the handlers
for handler in log.handlers:
    handler.close()
    log.removeFilter(handler)

कृपया देखें: https://docs.python.org/2/howto/logging-cookbook.html


4
अद्भुत जवाब, थोड़ा गड़बड़ है। प्रेम करें कि आप कैसे स्ट्रीम और फ़ाइलों के लिए विभिन्न स्तरों और स्वरूपों का उपयोग करते हैं। +1, लेकिन आत्मा में +2।
अनफिन कैट

मेरे लिए यह sys.stdoutपैरामीटर के बिना काम नहीं कियाch = logging.StreamHandler()
13

64

आप फ़ाइल और स्टडआउट के लिए दो हैंडलर बना सकते हैं और फिर handlersतर्क के साथ एक लकड़हारा बना सकते हैं basicConfig। यह उपयोगी हो सकता है यदि आपके पास दोनों लॉगर्स के लिए समान log_level और स्वरूप आउटपुट है:

import logging
import sys

file_handler = logging.FileHandler(filename='tmp.log')
stdout_handler = logging.StreamHandler(sys.stdout)
handlers = [file_handler, stdout_handler]

logging.basicConfig(
    level=logging.DEBUG, 
    format='[%(asctime)s] {%(filename)s:%(lineno)d} %(levelname)s - %(message)s',
    handlers=handlers
)

logger = logging.getLogger('LOGGER_NAME')

32

फाइल करने के लिए और stderr पर लॉग इन करने का सबसे सरल तरीका:

import logging

logging.basicConfig(filename="logfile.txt")
stderrLogger=logging.StreamHandler()
stderrLogger.setFormatter(logging.Formatter(logging.BASIC_FORMAT))
logging.getLogger().addHandler(stderrLogger)

यह कंसोल में लॉगिंग संदेश से पहले INFO, DEBUG और ERROR के लेबल नहीं दिखाता है। यह फ़ाइल में उन लेबल को दिखाता है। कंसोल में लेबल दिखाने के लिए कोई विचार?
जहीमस्टट

1
धन्यवाद, @ जेमिस्ट, मैंने फॉर्मैटर जोड़ा। दुर्भाग्य से, यह अब कोई छोटा नहीं है, लेकिन फिर भी सबसे सरल तरीका है। :-)
वीडेनड्राइंड

12

यहाँ शक्तिशाली लेकिन खराब प्रलेखित logging.config.dictConfigपद्धति पर आधारित एक समाधान है । प्रत्येक लॉग संदेश को भेजने के बजाय stdout, यह लॉग स्तर ERRORऔर उच्चतर stderrऔर अन्य सभी चीज़ों के साथ संदेश भेजता है stdout। यह उपयोगी हो सकता है अगर सिस्टम के अन्य भागों को सुन रहे हैं stderrया stdout

import logging
import logging.config
import sys

class _ExcludeErrorsFilter(logging.Filter):
    def filter(self, record):
        """Filters out log messages with log level ERROR (numeric value: 40) or higher."""
        return record.levelno < 40


config = {
    'version': 1,
    'filters': {
        'exclude_errors': {
            '()': _ExcludeErrorsFilter
        }
    },
    'formatters': {
        # Modify log message format here or replace with your custom formatter class
        'my_formatter': {
            'format': '(%(process)d) %(asctime)s %(name)s (line %(lineno)s) | %(levelname)s %(message)s'
        }
    },
    'handlers': {
        'console_stderr': {
            # Sends log messages with log level ERROR or higher to stderr
            'class': 'logging.StreamHandler',
            'level': 'ERROR',
            'formatter': 'my_formatter',
            'stream': sys.stderr
        },
        'console_stdout': {
            # Sends log messages with log level lower than ERROR to stdout
            'class': 'logging.StreamHandler',
            'level': 'DEBUG',
            'formatter': 'my_formatter',
            'filters': ['exclude_errors'],
            'stream': sys.stdout
        },
        'file': {
            # Sends all log messages to a file
            'class': 'logging.FileHandler',
            'level': 'DEBUG',
            'formatter': 'my_formatter',
            'filename': 'my.log',
            'encoding': 'utf8'
        }
    },
    'root': {
        # In general, this should be kept at 'NOTSET'.
        # Otherwise it would interfere with the log levels set for each handler.
        'level': 'NOTSET',
        'handlers': ['console_stderr', 'console_stdout', 'file']
    },
}

logging.config.dictConfig(config)

वास्तव में रूट लकड़हारा प्राप्त करने के लिए एक खाली स्ट्रिंग के लिए लकड़हारा का नाम बदलना पड़ा। अन्यथा बहुत मददगार, धन्यवाद!
न्यूटोपियन

8

चूंकि किसी ने एक स्वच्छ दो लाइनर साझा नहीं किए हैं, मैं अपना खुद का साझा करूंगा:

logging.basicConfig(filename='logs.log', level=logging.DEBUG, format="%(asctime)s:%(levelname)s: %(message)s")
logging.getLogger().addHandler(logging.StreamHandler())

2

यहाँ एक बहुत ही सरल उदाहरण दिया गया है:

import logging
l = logging.getLogger("test")

# Add a file logger
f = logging.FileHandler("test.log")
l.addHandler(f)

# Add a stream logger
s = logging.StreamHandler()
l.addHandler(s)

# Send a test message to both -- critical will always log
l.critical("test msg")

आउटपुट स्टडआउट और फ़ाइल में "टेस्ट संदेश" दिखाएगा।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.