ফাইল লগ করতে লডার কনফিগারেশন এবং 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 হবে লিখেছেন। আপনার স্ট্যাডারের উপর সত্যই যদি স্টডআউট দরকার হয় তা নিশ্চিত নন, তবে পাইথন লগার সেটআপ করার সময় আমি এটি ব্যবহার করি এবং আমি পাশাপাশি যুক্ত করি 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, এবং তারপরে এটি স্টডারারের পরিবর্তে লগ ইন করবে।
সিলাস রায়

1
@ sr2222 logger.addHandler (sys.stdout) আমাকে NameError দেয়: নাম 'sys' সংজ্ঞায়িত করা হয়নি
stdcerr

21
হ্যাঁ ... আপনাকে import sysপ্রথমে করতে হবে। এবং প্রকৃতপক্ষে হ্যান্ডলারটি সূচনা করুন, যেমনconsoleHandler = logging.StreamHandler(sys.stdout)
সিলাস রায়

15
কারণ যেমন আমি আগেই বলেছি, আপনি এটি কীভাবে করবেন না। Sys.stdout দিয়ে হ্যান্ডলারের তৈরি করুন, তারপরে হ্যান্ডলারটি লগারের সাথে সংযুক্ত করুন।
সিলাস রায়

6
rootLogger.setLevel(logging.DEBUG)আপনি যদি তথ্য বা ডিবাগ বার্তাগুলি দেখার চেষ্টা করে
যাচ্ছেন

246

logging.basicConfig()handlersপাইথন ৩.৩ থেকে একটি কীওয়ার্ড আর্গুমেন্ট নিতে পারে , যা লগিং সেটআপটিকে অনেক সহজ করে তোলে, বিশেষত একই ফর্ম্যাটারের সাহায্যে একাধিক হ্যান্ডলার সেটআপ করার সময়:

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)মূল প্রশ্ন এর প্রয়োজনীয়তা প্রতি - StreamHandler জন্য ডিফল্ট stderr হবে লিখতে হয় তাকান। LogRecord বৈশিষ্ট্যাবলী যদি আপনি লগ বিন্যাস কাস্টমাইজ এবং ফাইলের নাম / লাইন, থ্রেড তথ্য ইত্যাদি ভালো জিনিস যোগ করতে চান)

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

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

দ্রষ্টব্য: যদি এটি কাজ না করে, অন্য কেউ সম্ভবত ইতিমধ্যে লগিং সিস্টেমটিকে অন্যভাবে শুরু করেছেন। মন্তব্যগুলি logging.root.handlers = []কল করার আগে করার পরামর্শ দিচ্ছে basicConfig()


5
স্তর = লগিং.আইএনএফও বা পছন্দসই স্তরটি সেট করতে ভুলবেন না
অ্যান্ডি ম্যাটসন

5
জন্য সংজ্ঞা FileHandler: logging.FileHandler(filename, mode='a', encoding=None, delay=False)। এর অর্থ, আপনি যখন একই ফোল্ডারে লগইন করতে চান, আপনি কেবল ব্যবহার করতে পারেন FileHandler("mylog.log")। আপনি যদি প্রতিবার লগটি ওভাররাইট করতে চান তবে দ্বিতীয় যুক্তি হিসাবে "w" সেট করুন।
ব্যবহারকারী 136036

7
আমি এটি চেষ্টা করেছিলাম, তবে কনসোল আউটপুট দিচ্ছে তবে আউটপুট ফাইলটি খালি .. কোনও পরামর্শ ..?
রমেশ-এক্স

4
@ রমেশ-এক্স, এটি আমাকেও পাগল করেছে। logging.root.handlers = []কল করার আগে কেবল করুন basicConfig, ফাংশনটি একবার দেখুন - এটি বিরক্তিকর।
ইহাদানী

70

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

প্রশ্নটি থেকে ধরে নেওয়া মান এবং লগফিল পুনরায় ব্যবহার করার জন্য এখানে একটি দ্রুত উদাহরণ রয়েছে:

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যে push কর্মের বার্তা (যে বিষয়টি জন্য, বা অন্য কোন এটির যদি আপনি চান) রুট এটির থেকে stdout- এ।


5

একাধিক পাইথন প্যাকেজগুলিতে ওয়াটারবয়ের কোডটি বারবার ব্যবহার করার পরে, আমি অবশেষে এটি একটি ছোট স্টাইন্ডলোন পাইথন প্যাকেজে ফেলেছি, যা আপনি এখানে দেখতে পারেন:

https://github.com/acschaefer/duallog

কোডটি নথিভুক্ত এবং সহজেই ব্যবহারযোগ্য। কেবল .pyফাইলটি ডাউনলোড করুন এবং এটি আপনার প্রকল্পে অন্তর্ভুক্ত করুন বা এর মাধ্যমে পুরো প্যাকেজটি ইনস্টল করুন pip install duallog


কোনও কারণে কনসোলে লগইন করা হচ্ছে না না কোনও
ফাইলই

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

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

#!/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)
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.