การใช้ logging ใน Python3

  1. A simple example
  2. Logging to a file
  3. Logging from multiple modules
  4. Logging variable data
  5. Changing the format of displayed messages
  6. Displaying the date/time in messages
  7. Configuring Logging
  8. Logging Levels
  9. Using Handlers
  10. Capturing Stack Traces **
  11. Configuring Logging in a YAML format

A simple example

#!/usr/bin/python3

import logging
logging.warning('Watch out!')  # will print a message to the console
logging.info('I told you so')  # will not print anything

ผลการรัน

WARNING:root:Watch out!

Logging to a file

import logging
logging.basicConfig(filename='example.log',level=logging.DEBUG)
logging.debug('This message should go to the log file')
logging.info('So should this')
logging.warning('And this, too')

ผลการรันในไฟล์ example.log

DEBUG:root:This message should go to the log file
INFO:root:So should this
WARNING:root:And this, too

This example also shows how you can set the logging level which acts as the threshold for tracking. In this case, because we set the threshold to DEBUG, all of the messages were printed.

Logging from multiple modules

# myapp.py
import logging
import mylib

def main():
    logging.basicConfig(filename='myapp.log', level=logging.INFO)
    logging.info('Started')
    mylib.do_something()
    logging.info('Finished')

if __name__ == '__main__':
    main()
# mylib.py
import logging

def do_something():
    logging.info('Doing something')

ผลการรันในไฟล์  myapp.log:

INFO:root:Started
INFO:root:Doing something
INFO:root:Finished

Logging variable data

To log variable data, use a format string for the event description message and append the variable data as arguments.

import logging
logging.warning('%s before you %s', 'Look', 'leap!')

ผลการรัน

WARNING:root:Look before you leap!

Changing the format of displayed messages

import logging
logging.basicConfig(format='%(levelname)s:%(message)s', level=logging.DEBUG)
logging.debug('This message should appear on the console')
logging.info('So should this')
logging.warning('And this, too')

ผลการรัน

DEBUG:This message should appear on the console
INFO:So should this
WARNING:And this, too

Displaying the date/time in messages

import logging
logging.basicConfig(format='%(asctime)s %(message)s')
logging.warning('is when this event was logged.')

ผลการรัน

2021-09-15 13:37:34,794 is when this event was logged.

The default format for date/time display (shown above) is like ISO8601 or RFC 3339. If you need more control over the formatting of the date/time, provide a datefmt argument to basicConfig, as in this example:

import logging
logging.basicConfig(format='%(asctime)s %(message)s', datefmt='%m/%d/%Y %I:%M:%S %p')
logging.warning('is when this event was logged.')

ผลการรัน

09/15/2021 01:38:42 PM is when this event was logged.

The format of the datefmt argument is the same as supported by time.strftime().

Configuring Logging

Creating loggers, handlers, and formatters explicitly using Python code that calls the configuration methods listed above.

import logging

# create logger
logger = logging.getLogger('simple_example')
logger.setLevel(logging.DEBUG)

# create console handler and set level to debug
ch = logging.StreamHandler()
ch.setLevel(logging.DEBUG)

# create formatter
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')

# add formatter to ch
ch.setFormatter(formatter)

# add ch to logger
logger.addHandler(ch)

# 'application' code
logger.debug('debug message')
logger.info('info message')
logger.warning('warn message')
logger.error('error message')
logger.critical('critical message')

ผลการรัน

2021-09-15 13:45:40,226 - simple_example - DEBUG - debug message
2021-09-15 13:45:40,226 - simple_example - INFO - info message
2021-09-15 13:45:40,226 - simple_example - WARNING - warn message
2021-09-15 13:45:40,226 - simple_example - ERROR - error message
2021-09-15 13:45:40,226 - simple_example - CRITICAL - critical message

ทำไฟล์ config แยก

import logging
import logging.config

logging.config.fileConfig('logging.conf')

# create logger
logger = logging.getLogger('simpleExample')

# 'application' code
logger.debug('debug message')
logger.info('info message')
logger.warning('warn message')
logger.error('error message')
logger.critical('critical message')

ไฟล์ logging.conf

[loggers]
keys=root,simpleExample

[handlers]
keys=consoleHandler

[formatters]
keys=simpleFormatter

[logger_root]
level=DEBUG
handlers=consoleHandler

[logger_simpleExample]
level=DEBUG
handlers=consoleHandler
qualname=simpleExample
propagate=0

[handler_consoleHandler]
class=StreamHandler
level=DEBUG
formatter=simpleFormatter
args=(sys.stdout,)

[formatter_simpleFormatter]
format=%(asctime)s - %(name)s - %(levelname)s - %(message)s
datefmt=

ผลการรัน

2021-09-15 13:51:47,993 - simpleExample - DEBUG - debug message
2021-09-15 13:51:47,993 - simpleExample - INFO - info message
2021-09-15 13:51:47,993 - simpleExample - WARNING - warn message
2021-09-15 13:51:47,993 - simpleExample - ERROR - error message
2021-09-15 13:51:47,993 - simpleExample - CRITICAL - critical message

Logging Levels

LevelNumeric value
CRITICAL50
ERROR40
WARNING30
INFO20
DEBUG10
NOTSET0

Using Handlers

ตัวอย่าง console เซ็ตเป็น logging.WARNING ส่วน file เซ็ตเป็น logging.ERROR

# logging_example.py

import logging

# Create a custom logger
logger = logging.getLogger(__name__)

# Create handlers
c_handler = logging.StreamHandler()
f_handler = logging.FileHandler('file.log')
c_handler.setLevel(logging.WARNING)
f_handler.setLevel(logging.ERROR)

# Create formatters and add it to handlers
c_format = logging.Formatter('%(name)s - %(levelname)s - %(message)s')
f_format = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
c_handler.setFormatter(c_format)
f_handler.setFormatter(f_format)

# Add handlers to the logger
logger.addHandler(c_handler)
logger.addHandler(f_handler)

logger.warning('This is a warning')
logger.error('This is an error')

ผลการรันที่ console

__main__ - WARNING - This is a warning
__main__ - ERROR - This is an error

ผลการรันที่ไฟล์ file.log

2021-09-15 14:04:23,318 - __main__ - ERROR - This is an error

Capturing Stack Traces

import logging

a = 5
b = 0

try:
  c = a / b
except Exception as e:
  logging.error("Exception occurred", exc_info=True)

หรือ

import logging

a = 5
b = 0
try:
  c = a / b
except Exception as e:
  logging.exception("Exception occurred")

ผลการรัน

ERROR:root:Exception occurred
Traceback (most recent call last):
  File "./helloworld.py", line 7, in <module>
    c = a / b
ZeroDivisionError: division by zero

Configuring Logging in a YAML format

ติดตั้ง PyYAML

python3 -m pip install pyyaml

Python 3.8 บน Windows ให้เพิ่ม C:\Users\jack\AppData\Local\Programs\Python\Python38\Scripts เข้าไปในตัวแปร PATH แล้วรัน

C:\Users\jack\AppData\Local\Programs\Python\Python38\python.exe -m pip install --upgrade pip
C:\Users\jack\AppData\Local\Programs\Python\Python38\python.exe -m pip install pyyaml

ไฟล์ config.yaml

version: 1
formatters:
  simple:
    format: '%(asctime)s - %(name)s - %(levelname)s - %(message)s'
handlers:
  console:
    class: logging.StreamHandler
    level: DEBUG
    formatter: simple
    stream: ext://sys.stdout
loggers:
  sampleLogger:
    level: DEBUG
    handlers: [console]
    propagate: no
root:
  level: DEBUG
  handlers: [console]
import logging
import logging.config
import yaml

with open('config.yaml', 'r', encoding='utf8') as f:
    config = yaml.safe_load(f.read())
    logging.config.dictConfig(config)

logger = logging.getLogger(__name__)

logger.debug('This is a debug message')

ผลการรัน

2021-09-15 14:30:42,270 - __main__ - DEBUG - This is a debug message