Làm thế nào để ghi vào một tệp, bằng cách sử dụng mô-đun Python ghi nhật ký?


128

Làm cách nào để sử dụng mô-đun ghi nhật ký bằng Python để ghi vào tệp? Mỗi khi tôi cố gắng sử dụng nó, nó chỉ in ra thông báo.

Câu trả lời:


171

Một ví dụ về việc sử dụng logging.basicConfigthay vìlogging.fileHandler()

logging.basicConfig(filename=logname,
                            filemode='a',
                            format='%(asctime)s,%(msecs)d %(name)s %(levelname)s %(message)s',
                            datefmt='%H:%M:%S',
                            level=logging.DEBUG)

logging.info("Running Urban Planning")

self.logger = logging.getLogger('urbanGUI')

Theo thứ tự, năm phần thực hiện như sau:

  1. đặt tệp đầu ra ( filename=logname)
  2. đặt nó thành append thay vì ghi đè ( filemode='a')
  3. xác định định dạng của thông báo đầu ra ( format=...)
  4. xác định định dạng của thời gian đầu ra ( datefmt='%H:%M:%S')
  5. và xác định mức thông báo tối thiểu mà nó sẽ chấp nhận ( level=logging.DEBUG).

Tên tệp có thể là một vị trí hdfs không? Nếu có, làm thế nào?
Gia tăng Jacob vào

có thể đặt đường dẫn tệp không
neeraja

1
đảm bảo điều này là không dưới if __name__ == '__main__':nếu chạy trên apache
Rami Alloush

@RamiAlloush bạn có thể vui lòng nói rõ hơn được không? Tại sao vậy? (tò mò :))
báo

@notihs, máy chủ không chạy trực tiếp tệp tập lệnh nên phần bên dưới if __name__ == '__main__':không được thực thi.
Rami Alloush

71

Lấy từ " sách nấu ăn ghi nhật ký ":

# create logger with 'spam_application'
logger = logging.getLogger('spam_application')
logger.setLevel(logging.DEBUG)
# create file handler which logs even debug messages
fh = logging.FileHandler('spam.log')
fh.setLevel(logging.DEBUG)
logger.addHandler(fh)

Và bạn tốt để đi.

PS Hãy chắc chắn rằng bạn cũng đọc cách ghi nhật ký HOWTO .


4
Để trả lời câu hỏi đầu tiên của bạn, vui lòng xem tiêu đề của câu hỏi tôi đã hỏi. Tôi đã xem qua liên kết bạn cung cấp và nó hữu ích. Tôi đã sao chép mã bạn cung cấp cho tôi và tôi đã nhầm khi cho rằng mình có thể sử dụng thành công logger.info ("message") và logger.warning ("message")? Tôi đã có thể ghi vào tệp bằng cách sử dụng logger.warning, tuy nhiên, logger.info dường như không ghi vào tệp.
Takkun

Thử xóa lệnh gọi setLevel. Đọc tài liệu của trình xử lý, có vẻ như tất cả các thư đều được xử lý theo mặc định.
thegrinner

2
Tôi có thể ghi ra tệp chỉ bằng cách sử dụng logger.warning("message"), không thể sử dụng logger.info("message")cũng không logger.debug("message"). Đó là một chút khó chịu.
m3nda

3
Ví dụ mã @EliBendersky đã viết thiếu 1 bước nếu bạn muốn viết thông tin / tin nhắn gỡ lỗi. Bản thân trình ghi nhật ký cần có cấp độ nhật ký riêng của nó được cấu hình để chấp nhận cấp độ ghi nhật ký đó, ví dụ logger.setLevel(logging.DEBUG). Bộ ghi nhật ký có thể được cấu hình với nhiều bộ xử lý; mức được định cấu hình trong trình ghi nhật ký xác định thông điệp nhật ký mức độ nghiêm trọng nào sẽ gửi đến từng trình xử lý của nó và các mức được đặt trong trình xử lý xác định mức mà trình xử lý sẽ xử lý. Lưu ý rằng những người muốn in thông báo thông tin chỉ cần đặt điều này INFOtrong cả trình ghi nhật ký và trình xử lý.
testworks

Tôi đã cập nhật mẫu để làm logger.setLevel(logging.DEBUG)- nhờ cho ý kiến
Eli Bendersky

13

Tôi thích sử dụng tệp cấu hình hơn. Nó cho phép tôi chuyển đổi cấp độ ghi nhật ký, vị trí, v.v. mà không cần thay đổi mã khi tôi chuyển từ phát triển sang phát hành. Tôi chỉ đơn giản đóng gói một tệp cấu hình khác có cùng tên và với cùng các trình ghi được xác định.

import logging.config
if __name__ == '__main__':
    # Configure the logger
    # loggerConfigFileName: The name and path of your configuration file
    logging.config.fileConfig(path.normpath(loggerConfigFileName))

    # Create the logger
    # Admin_Client: The name of a logger defined in the config file
    mylogger = logging.getLogger('Admin_Client')

    msg='Bite Me'
    myLogger.debug(msg)
    myLogger.info(msg)
    myLogger.warn(msg)
    myLogger.error(msg)
    myLogger.critical(msg)

    # Shut down the logger
    logging.shutdown()

Đây là mã của tôi cho tệp cấu hình nhật ký

#These are the loggers that are available from the code
#Each logger requires a handler, but can have more than one
[loggers]
keys=root,Admin_Client


#Each handler requires a single formatter
[handlers]
keys=fileHandler, consoleHandler


[formatters]
keys=logFormatter, consoleFormatter


[logger_root]
level=DEBUG
handlers=fileHandler


[logger_Admin_Client]
level=DEBUG
handlers=fileHandler, consoleHandler
qualname=Admin_Client
#propagate=0 Does not pass messages to ancestor loggers(root)
propagate=0


# Do not use a console logger when running scripts from a bat file without a console
# because it hangs!
[handler_consoleHandler]
class=StreamHandler
level=DEBUG
formatter=consoleFormatter
args=(sys.stdout,)# The comma is correct, because the parser is looking for args


[handler_fileHandler]
class=FileHandler
level=DEBUG
formatter=logFormatter
# This causes a new file to be created for each script
# Change time.strftime("%Y%m%d%H%M%S") to time.strftime("%Y%m%d")
# And only one log per day will be created. All messages will be amended to it.
args=("D:\\Logs\\PyLogs\\" + time.strftime("%Y%m%d%H%M%S")+'.log', 'a')


[formatter_logFormatter]
#name is the name of the logger root or Admin_Client
#levelname is the log message level debug, warn, ect 
#lineno is the line number from where the call to log is made
#04d is simple formatting to ensure there are four numeric places with leading zeros
#4s would work as well, but would simply pad the string with leading spaces, right justify
#-4s would work as well, but would simply pad the string with trailing spaces, left justify
#filename is the file name from where the call to log is made
#funcName is the method name from where the call to log is made
#format=%(asctime)s | %(lineno)d | %(message)s
#format=%(asctime)s | %(name)s | %(levelname)s | %(message)s
#format=%(asctime)s | %(name)s | %(module)s-%(lineno) | %(levelname)s | %(message)s
#format=%(asctime)s | %(name)s | %(module)s-%(lineno)04d | %(levelname)s | %(message)s
#format=%(asctime)s | %(name)s | %(module)s-%(lineno)4s | %(levelname)-8s | %(message)s

format=%(asctime)s | %(levelname)-8s | %(lineno)04d | %(message)s


#Use a separate formatter for the console if you want
[formatter_consoleFormatter]
format=%(asctime)s | %(levelname)-8s | %(filename)s-%(funcName)s-%(lineno)04d | %(message)s

1
Đặt tên tệp bằng ngày tháng yêu cầu gấp đôi %%trong Python 3. Ví dụtime.strftime("%%Y%%m%%D")
AH

9

http://docs.python.org/library/logging.html#logging.basicConfig

logging.basicConfig(filename='/path/to/your/log', level=....)

1
Điều này giúp lưu các bản ghi trong tệp, điều đó thật tốt. Điều gì sẽ xảy ra nếu cùng với điều này, tôi cũng muốn nó ghi lại các kết quả đầu ra trên thiết bị đầu cuối?
Rishabh Agrahari

loggingTài liệu mô-đun chính thức cho phép điều này. Bạn thậm chí có thể chọn nhật ký nào đi vào thiết bị đầu cuối và nhật ký nào đi vào tệp, và nhiều ứng dụng thú vị khác. docs.python.org/3/howto/…
Daniel Hernandez

4

đây là một cách đơn giản hơn để thực hiện nó. giải pháp này không sử dụng từ điển cấu hình và sử dụng trình xử lý tệp xoay vòng, như sau:

import logging
from logging.handlers import RotatingFileHandler

logging.basicConfig(handlers=[RotatingFileHandler(filename=logpath+filename,
                     mode='w', maxBytes=512000, backupCount=4)], level=debug_level,
                     format='%(levelname)s %(asctime)s %(message)s', 
                    datefmt='%m/%d/%Y%I:%M:%S %p')

logger = logging.getLogger('my_logger')

hoặc như vậy:

import logging
from logging.handlers import RotatingFileHandler

handlers = [
            RotatingFileHandler(filename=logpath+filename, mode='w', maxBytes=512000, 
                                backupCount=4)
           ]
logging.basicConfig(handlers=handlers, level=debug_level, 
                    format='%(levelname)s %(asctime)s %(message)s', 
                    datefmt='%m/%d/%Y%I:%M:%S %p')

logger = logging.getLogger('my_logger')

biến trình xử lý cần phải là biến có thể lặp lại. logpath + tên tệp và debug_level chỉ là các biến chứa thông tin tương ứng. tất nhiên, các giá trị cho các tham số hàm là tùy thuộc vào bạn.

lần đầu tiên tôi sử dụng mô-đun ghi nhật ký, tôi đã mắc lỗi viết như sau, điều này tạo ra lỗi khóa tệp hệ điều hành (ở trên là giải pháp cho điều đó):

import logging
from logging.handlers import RotatingFileHandler

logging.basicConfig(filename=logpath+filename, level=debug_level, format='%(levelname)s %(asctime)s %(message)s', datefmt='%m/%d/%Y
 %I:%M:%S %p')

logger = logging.getLogger('my_logger')
logger.addHandler(RotatingFileHandler(filename=logpath+filename, mode='w', 
                  maxBytes=512000, backupCount=4))

và Bob là chú của bạn!


3

http://docs.python.org/library/logging.handlers.html#filehandler

Các FileHandlerlớp học, nằm trong lõi logginggói, gửi sản lượng khai thác gỗ vào một tập tin đĩa.


3
+1 Để có ví dụ hoàn chỉnh, hãy xem "hướng dẫn cơ bản": docs.python.org/howto/logging.html#logging-to-a-file
Ferdinand Beyer

Tôi cũng thích cách có một số kiểu chữ khác nhau FileHandlercho các tình huống khác nhau. ( WatchedFileHandler, RotatingFileHandlerv.v.)
JAB

0
import sys
import logging

from util import reducer_logfile
logging.basicConfig(filename=reducer_logfile, format='%(message)s',
                    level=logging.INFO, filemode='w')

0

Ví dụ này sẽ hoạt động tốt. Tôi đã thêm streamhandler cho bảng điều khiển. Nhật ký bảng điều khiển và dữ liệu xử lý tệp phải giống nhau.

    # MUTHUKUMAR_TIME_DATE.py #>>>>>>>> file name(module)

    import sys
    import logging
    import logging.config
    # ================== Logger ================================
    def Logger(file_name):
        formatter = logging.Formatter(fmt='%(asctime)s %(module)s,line: %(lineno)d %(levelname)8s | %(message)s',
                                      datefmt='%Y/%m/%d %H:%M:%S') # %I:%M:%S %p AM|PM format
        logging.basicConfig(filename = '%s.log' %(file_name),format= '%(asctime)s %(module)s,line: %(lineno)d %(levelname)8s | %(message)s',
                                      datefmt='%Y/%m/%d %H:%M:%S', filemode = 'w', level = logging.INFO)
        log_obj = logging.getLogger()
        log_obj.setLevel(logging.DEBUG)
        # log_obj = logging.getLogger().addHandler(logging.StreamHandler())

        # console printer
        screen_handler = logging.StreamHandler(stream=sys.stdout) #stream=sys.stdout is similar to normal print
        screen_handler.setFormatter(formatter)
        logging.getLogger().addHandler(screen_handler)

        log_obj.info("Logger object created successfully..")
        return log_obj
    # =======================================================


MUTHUKUMAR_LOGGING_CHECK.py #>>>>>>>>>>> file name
# calling **Logger** function
file_name = 'muthu'
log_obj =Logger(file_name)
log_obj.info("yes   hfghghg ghgfh".format())
log_obj.critical("CRIC".format())
log_obj.error("ERR".format())
log_obj.warning("WARN".format())
log_obj.debug("debug".format())
log_obj.info("qwerty".format())
log_obj.info("asdfghjkl".format())
log_obj.info("zxcvbnm".format())
# closing file
log_obj.handlers.clear()

OUTPUT:
2019/07/13 23:54:40 MUTHUKUMAR_TIME_DATE,line: 17     INFO | Logger object created successfully..
2019/07/13 23:54:40 MUTHUKUMAR_LOGGING_CHECK,line: 8     INFO | yes   hfghghg ghgfh
2019/07/13 23:54:40 MUTHUKUMAR_LOGGING_CHECK,line: 9 CRITICAL | CRIC
2019/07/13 23:54:40 MUTHUKUMAR_LOGGING_CHECK,line: 10    ERROR | ERR
2019/07/13 23:54:40 MUTHUKUMAR_LOGGING_CHECK,line: 11  WARNING | WARN
2019/07/13 23:54:40 MUTHUKUMAR_LOGGING_CHECK,line: 12    DEBUG | debug
2019/07/13 23:54:40 MUTHUKUMAR_LOGGING_CHECK,line: 13     INFO | qwerty
2019/07/13 23:54:40 MUTHUKUMAR_LOGGING_CHECK,line: 14     INFO | asdfghjkl
2019/07/13 23:54:40 MUTHUKUMAR_LOGGING_CHECK,line: 15     INFO | zxcvbnm

Thanks, 

0

Định dạng mô tả

#%(name)s       Name of the logger (logging channel).
#%(levelname)s  Text logging level for the message ('DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL').
#%(asctime)s    Human-readable time when the LogRecord was created. By default this is of the form ``2003-07-08 16:49:45,896'' (the numbers after the comma are millisecond portion of the time).
#%(message)s    The logged message. 

Cách gọi thông thường

import logging
#logging.basicConfig(level=logging.INFO)
logging.basicConfig(level=logging.DEBUG)
logger = logging.getLogger(__name__)
logger.info('Start reading database')
# read database here
records = {'john': 55, 'tom': 66}
logger.debug('Records: %s', records)
logger.info('Updating records ...')
# update records here
logger.info('Finish updating records')

Đầu ra

INFO:__main__:Start reading database
DEBUG:__main__:Records: {'john': 55, 'tom': 66}
INFO:__main__:Updating records ...
INFO:__main__:Finish updating records

Sử dụng giá trị Dict, Call

import logging
import logging.config
import otherMod2

def main():
    """
    Based on http://docs.python.org/howto/logging.html#configuring-logging
    """
    dictLogConfig = {
        "version":1,
        "handlers":{
                    "fileHandler":{
                        "class":"logging.FileHandler",
                        "formatter":"myFormatter",
                        "filename":"config2.log"
                        }
                    },        
        "loggers":{
            "exampleApp":{
                "handlers":["fileHandler"],
                "level":"INFO",
                }
            },

        "formatters":{
            "myFormatter":{
                "format":"%(asctime)s - %(name)s - %(levelname)s - %(message)s"
                }
            }
        }

    logging.config.dictConfig(dictLogConfig)

    logger = logging.getLogger("exampleApp")

    logger.info("Program started")
    result = otherMod2.add(7, 8)
    logger.info("Done!")

if __name__ == "__main__":
    main()

otherMod2.py

import logging
def add(x, y):
    """"""
    logger = logging.getLogger("exampleApp.otherMod2.add")
    logger.info("added %s and %s to get %s" % (x, y, x+y))
    return x+y

Đầu ra

2019-08-12 18:03:50,026 - exampleApp - INFO - Program started
2019-08-12 18:03:50,026 - exampleApp.otherMod2.add - INFO - added 7 and 8 to get 15
2019-08-12 18:03:50,027 - exampleApp - INFO - Done!
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.