लकड़हारा विन्यास फाइल करने के लिए लॉग इन करें और stdout में प्रिंट करें


353

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

import logging
import logging.handlers
logger = logging.getLogger("")
logger.setLevel(logging.DEBUG)
handler = logging.handlers.RotatingFileHandler(
    LOGFILE, maxBytes=(1048576*5), backupCount=7
)
formatter = logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s")
handler.setFormatter(formatter)
logger.addHandler(handler)

और फिर एक लकड़हारा फ़ंक्शन को कॉल करें

logger.debug("I am written to the file")

यहाँ कुछ मदद के लिए धन्यवाद!

जवाबों:


451

बस रूट लकड़हारा के लिए एक संभाल पाने के लिए और जोड़ें StreamHandlerStreamHandlerStderr करने के लिए लिखता है। यकीन नहीं है कि अगर आपको वास्तव में stderr पर stdout की आवश्यकता है, लेकिन यही वह चीज है जिसका उपयोग मैं तब करता हूं जब मैं Python लकड़हारा सेटअप करता हूं और FileHandlerसाथ ही साथ मैं भी जोड़ता हूं । फिर मेरे सभी लॉग दोनों स्थानों पर जाते हैं (जो कि जैसा आप चाहते हैं वह लगता है)।

import logging
logging.getLogger().addHandler(logging.StreamHandler())

यदि आप stdoutइसके बजाय आउटपुट करना चाहते हैं stderr, तो आपको इसे StreamHandlerकंस्ट्रक्टर को निर्दिष्ट करने की आवश्यकता है ।

import sys
# ...
logging.getLogger().addHandler(logging.StreamHandler(sys.stdout))

आप Formatterइसमें एक जोड़ भी सकते हैं ताकि आपकी सभी लॉग लाइनों में एक सामान्य हेडर हो।

अर्थात:

import logging
logFormatter = logging.Formatter("%(asctime)s [%(threadName)-12.12s] [%(levelname)-5.5s]  %(message)s")
rootLogger = logging.getLogger()

fileHandler = logging.FileHandler("{0}/{1}.log".format(logPath, fileName))
fileHandler.setFormatter(logFormatter)
rootLogger.addHandler(fileHandler)

consoleHandler = logging.StreamHandler()
consoleHandler.setFormatter(logFormatter)
rootLogger.addHandler(consoleHandler)

के प्रारूप को प्रिंट करता है:

2012-12-05 16:58:26,618 [MainThread  ] [INFO ]  my message

19
तुम भी बस के StreamHandlerसाथ शुरू कर सकता है sys.stdout, और फिर यह stderr के बजाय उस के लिए लॉग इन करेंगे।
सिलस रे

1
@ sr2222 logger.addHandler (sys.stdout) मुझे NameError देता है: नाम 'sys' परिभाषित नहीं है
stdcerr

21
खैर हाँ ... आपको import sysपहले करना होगा। और वास्तव में हैंडलर को इनिशियलाइज़ करते हैं, यानीconsoleHandler = logging.StreamHandler(sys.stdout)
सिलास रे

15
क्योंकि जैसा कि मैंने पहले ही कहा, कि आप इसे कैसे करते हैं। HANDLER को sys.stdout के साथ बनाएं, फिर हैंडलर को लकड़हारे से जोड़ दें।
सिलस रे

6
rootLogger.setLevel(logging.DEBUG)यदि आप जानकारी या डिबग संदेश देखने की कोशिश कर रहे हैं , तो भूल न जाएं
तूफान_m2138

247

logging.basicConfig()handlersपायथन 3.3 के बाद से एक कीवर्ड तर्क ले सकता है , जो लॉगिंग सेटअप को बहुत सरल करता है, खासकर जब एक ही फॉर्मूले के साथ कई हैंडलर सेट करते हैं:

handlers- यदि निर्दिष्ट किया गया है, तो यह रूट लॉगर में जोड़ने के लिए पहले से निर्मित हैंडलर का पुनरावृत्ति होना चाहिए। किसी भी हैंडलर के पास जो पहले से ही फॉर्मेटर सेट नहीं है, उसे इस फ़ंक्शन में बनाए गए डिफ़ॉल्ट फॉर्मैटर को सौंपा जाएगा।

पूरे सेटअप को इस तरह एकल कॉल के साथ किया जा सकता है:

import logging

logging.basicConfig(
    level=logging.INFO,
    format="%(asctime)s [%(levelname)s] %(message)s",
    handlers=[
        logging.FileHandler("debug.log"),
        logging.StreamHandler()
    ]
)

(या मूल प्रश्न की आवश्यकताओं के अनुसार import sys+ के साथ StreamHandler(sys.stdout)- स्ट्रीमहैंडलर के लिए डिफ़ॉल्ट को stderr पर लिखना है। LogRecord विशेषताओं को देखें यदि आप लॉग प्रारूप को अनुकूलित करना चाहते हैं और फ़ाइल नाम / रेखा, थ्रेड जानकारी आदि जैसी चीजों को जोड़ना चाहते हैं)

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

logging.info('Useful message')
logging.error('Something bad happened')
...

नोट: यदि यह काम नहीं करता है, तो किसी और ने शायद लॉगिंग सिस्टम को पहले से अलग कर दिया है। टिप्पणियां logging.root.handlers = []कॉल करने से पहले करने का सुझाव देती हैं basicConfig()


5
साथ ही निर्धारित स्तर = logging.INFO या वांछित स्तर तक भूल नहीं है
एंडी Matteson

5
के लिए परिभाषा FileHandler: logging.FileHandler(filename, mode='a', encoding=None, delay=False)। इसका मतलब है, कि जब आप एक ही फ़ोल्डर में लॉग इन करना चाहते हैं, तो आप बस उपयोग कर सकते हैं FileHandler("mylog.log")। यदि आप हर बार लॉग को ओवरराइट करना चाहते हैं, तो "w" को दूसरे तर्क के रूप में सेट करें।
user136036

7
मैंने यह कोशिश की, लेकिन आउटपुट फ़ाइल खाली है, हालांकि कंसोल आउटपुट दे रहा है .. कोई सुझाव ..?
रमेश-एक्स

4
@ रमेश-एक्स, इसने मुझे भी पागल कर दिया। बस करो logging.root.handlers = []इससे पहले कि करने के लिए कॉल basicConfig, समारोह पर एक नज़र डालें - यह कष्टप्रद है।
.हदन

70

बिना तर्कों के एक स्ट्रीमहैंडलर जोड़ने से स्टडआउट के बजाय स्टडर पर चला जाता है। यदि कुछ अन्य प्रक्रिया में स्टडआउट डंप पर निर्भरता है (यानी NRPE प्लगइन लिखते समय), तो स्पष्ट रूप से स्टडआउट निर्दिष्ट करना सुनिश्चित करें या आप कुछ अप्रत्याशित परेशानियों में भाग सकते हैं।

इस प्रश्न से ग्रहण किए गए मूल्यों और लोगो को पुन: उपयोग करने का एक त्वरित उदाहरण है:

import logging
from logging.handlers import RotatingFileHandler
from logging import handlers
import sys

log = logging.getLogger('')
log.setLevel(logging.DEBUG)
format = logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s")

ch = logging.StreamHandler(sys.stdout)
ch.setFormatter(format)
log.addHandler(ch)

fh = handlers.RotatingFileHandler(LOGFILE, maxBytes=(1048576*5), backupCount=7)
fh.setFormatter(format)
log.addHandler(fh)

मैं यह कोशिश कर रहा हूँ।
अजय कुमार

19

या तो चलाने के basicConfigसाथ stream=sys.stdoutएक जोड़ने के किसी अन्य संचालकों को सेट करने या कोई संदेश लॉग इन करने, या मैन्युअल रूप से पहले तर्क के रूप में StreamHandlerहै कि धक्का संदेश (उस बात के लिए, या किसी अन्य लकड़हारा आप चाहते हैं) जड़ लकड़हारा के लिए stdout।


5

कई पायथन पैकेजों में वाटरबॉय के कोड का उपयोग करने के बाद, मैंने अंत में इसे एक छोटे स्टैंडअलोन पायथन पैकेज में डाला, जिसे आप यहां पा सकते हैं:

https://github.com/acschaefer/duallog

कोड अच्छी तरह से प्रलेखित है और उपयोग में आसान है। बस .pyफ़ाइल डाउनलोड करें और इसे अपनी परियोजना में शामिल करें, या पूरे पैकेज को स्थापित करें pip install duallog


किसी कारणवश कंसोल न तो फाइल में लॉग इन हो रहा है और न ही फाइल (खाली है)
JackTheKnife

5

करने के लिए लॉग इन करना stdoutऔर rotating fileविभिन्न स्तरों और प्रारूपों के साथ:

import logging
import logging.handlers
import sys

if __name__ == "__main__":

    # Change root logger level from WARNING (default) to NOTSET in order for all messages to be delegated.
    logging.getLogger().setLevel(logging.NOTSET)

    # Add stdout handler, with level INFO
    console = logging.StreamHandler(sys.stdout)
    console.setLevel(logging.INFO)
    formater = logging.Formatter('%(name)-13s: %(levelname)-8s %(message)s')
    console.setFormatter(formater)
    logging.getLogger().addHandler(console)

    # Add file rotating handler, with level DEBUG
    rotatingHandler = logging.handlers.RotatingFileHandler(filename='rotating.log', maxBytes=1000, backupCount=5)
    rotatingHandler.setLevel(logging.DEBUG)
    formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
    rotatingHandler.setFormatter(formatter)
    logging.getLogger().addHandler(rotatingHandler)

    log = logging.getLogger("app." + __name__)

    log.debug('Debug message, should only appear in the file.')
    log.info('Info message, should appear in file and stdout.')
    log.warning('Warning message, should appear in file and stdout.')
    log.error('Error message, should appear in file and stdout.')

2

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

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

# -------------------------------------------------------------------------------
#                                                                               -
#  Python dual-logging setup (console and log file),                            -
#  supporting different log levels and colorized output                         -
#                                                                               -
#  Created by Fonic <https://github.com/fonic>                                  -
#  Date: 04/05/20                                                               -
#                                                                               -
#  Based on:                                                                    -
#  https://stackoverflow.com/a/13733863/1976617                                 -
#  https://uran198.github.io/en/python/2016/07/12/colorful-python-logging.html  -
#  https://en.wikipedia.org/wiki/ANSI_escape_code#Colors                        -
#                                                                               -
# -------------------------------------------------------------------------------

# Imports
import os
import sys
import logging

# Logging formatter supporting colored output
class LogFormatter(logging.Formatter):

    COLOR_CODES = {
        logging.CRITICAL: "\033[1;35m", # bright/bold magenta
        logging.ERROR:    "\033[1;31m", # bright/bold red
        logging.WARNING:  "\033[1;33m", # bright/bold yellow
        logging.INFO:     "\033[0;37m", # white / light gray
        logging.DEBUG:    "\033[1;30m"  # bright/bold black / dark gray
    }

    RESET_CODE = "\033[0m"

    def __init__(self, color, *args, **kwargs):
        super(LogFormatter, self).__init__(*args, **kwargs)
        self.color = color

    def format(self, record, *args, **kwargs):
        if (self.color == True and record.levelno in self.COLOR_CODES):
            record.color_on  = self.COLOR_CODES[record.levelno]
            record.color_off = self.RESET_CODE
        else:
            record.color_on  = ""
            record.color_off = ""
        return super(LogFormatter, self).format(record, *args, **kwargs)

# Setup logging
def setup_logging(console_log_output, console_log_level, console_log_color, logfile_file, logfile_log_level, logfile_log_color, log_line_template):

    # Create logger
    # For simplicity, we use the root logger, i.e. call 'logging.getLogger()'
    # without name argument. This way we can simply use module methods for
    # for logging throughout the script. An alternative would be exporting
    # the logger, i.e. 'global logger; logger = logging.getLogger("<name>")'
    logger = logging.getLogger()

    # Set global log level to 'debug' (required for handler levels to work)
    logger.setLevel(logging.DEBUG)

    # Create console handler
    console_log_output = console_log_output.lower()
    if (console_log_output == "stdout"):
        console_log_output = sys.stdout
    elif (console_log_output == "stderr"):
        console_log_output = sys.stderr
    else:
        print("Failed to set console output: invalid output: '%s'" % console_log_output)
        return False
    console_handler = logging.StreamHandler(console_log_output)

    # Set console log level
    try:
        console_handler.setLevel(console_log_level.upper()) # only accepts uppercase level names
    except:
        print("Failed to set console log level: invalid level: '%s'" % console_log_level)
        return False

    # Create and set formatter, add console handler to logger
    console_formatter = LogFormatter(fmt=log_line_template, color=console_log_color)
    console_handler.setFormatter(console_formatter)
    logger.addHandler(console_handler)

    # Create log file handler
    try:
        logfile_handler = logging.FileHandler(logfile_file)
    except Exception as exception:
        print("Failed to set up log file: %s" % str(exception))
        return False

    # Set log file log level
    try:
        logfile_handler.setLevel(logfile_log_level.upper()) # only accepts uppercase level names
    except:
        print("Failed to set log file log level: invalid level: '%s'" % logfile_log_level)
        return False

    # Create and set formatter, add log file handler to logger
    logfile_formatter = LogFormatter(fmt=log_line_template, color=logfile_log_color)
    logfile_handler.setFormatter(logfile_formatter)
    logger.addHandler(logfile_handler)

    # Success
    return True

# Main function
def main():

    # Setup logging
    script_name = os.path.splitext(os.path.basename(sys.argv[0]))[0]
    if (not setup_logging(console_log_output="stdout", console_log_level="warning", console_log_color=True,
                        logfile_file=script_name + ".log", logfile_log_level="debug", logfile_log_color=False,
                        log_line_template="%(color_on)s[%(created)d] [%(threadName)s] [%(levelname)-8s] %(message)s%(color_off)s")):
        print("Failed to setup logging, aborting.")
        return 1

    # Log some messages
    logging.debug("Debug message")
    logging.info("Info message")
    logging.warning("Warning message")
    logging.error("Error message")
    logging.critical("Critical message")

# Call main function
if (__name__ == "__main__"):
    sys.exit(main())

-4

2.7 के लिए, निम्नलिखित प्रयास करें:

fh = logging.handlers.RotatingFileHandler(LOGFILE, maxBytes=(1048576*5), backupCount=7)
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.