Tôi muốn thêm giải pháp của mình [dựa trên việc ghi nhật ký Cookbook và các bài viết và đề xuất khác từ chủ đề này. Tuy nhiên, tôi phải mất khá nhiều thời gian để tìm ra, tại sao nó không hoạt động ngay lập tức tôi mong đợi. Vì vậy, tôi đã tạo ra một chút Dự án kiểm tra để tìm hiểu làm thế nào ghi nhật ký đang hoạt động.
Vì tôi đã tìm ra nó, tôi muốn chia sẻ giải pháp của mình, có lẽ nó có thể giúp đỡ ai đó.
Tôi biết một số mã của tôi có thể không phải là thực hành tốt nhất, nhưng tôi vẫn đang học. Tôi đã để lại các chức năng print[]
trong đó, vì tôi đã sử dụng chúng, trong khi ghi nhật ký không hoạt động như mong đợi. Chúng được xóa trong ứng dụng khác của tôi. Ngoài ra tôi hoan nghênh bất kỳ phản hồi nào về bất kỳ phần nào của mã hoặc cấu trúc.
cấu trúc dự án my_log_test [được nhân bản/đơn giản hóa từ một dự án khác mà tôi đang làm] [cloned/simplified from another project I work on]
my_log_test
├── __init__.py
├── __main__.py
├── daemon.py
├── common
│ ├── my_logger.py
├── pkg1
│ ├── __init__.py
│ └── mod1.py
└── pkg2
├── __init__.py
└── mod2.py
Yêu cầu
Một vài điều khác biệt hoặc tôi chưa thấy được đề cập rõ ràng trong sự kết hợp mà tôi sử dụng:
- Mô -đun chính được gọi là
__main__.py
được gọi bởi__main__.py
- Tôi muốn có thể gọi các mô -đun
mod1.py
và
0 một cách riêng biệt trong khi phát triển/thử nghiệm## my_logger.py from datetime import datetime import time import os ## Init logging start import logging import logging.handlers def logger_init[]: print["print in my_logger.logger_init[]"] print["print my_logger.py __name__: " +__name__] path = "log/" filename = "my_log_test.log" ## get logger #logger = logging.getLogger[__name__] ## this was my mistake, to init a module logger here logger = logging.getLogger[] ## root logger logger.setLevel[logging.INFO] # File handler logfilename = datetime.now[].strftime["%Y%m%d_%H%M%S"] + f"_{filename}" file = logging.handlers.TimedRotatingFileHandler[f"{path}{logfilename}", when="midnight", interval=1] #fileformat = logging.Formatter["%[asctime]s [%[levelname]s] %[message]s"] fileformat = logging.Formatter["%[asctime]s [%[levelname]s]: %[name]s: %[message]s"] file.setLevel[logging.INFO] file.setFormatter[fileformat] # Stream handler stream = logging.StreamHandler[] #streamformat = logging.Formatter["%[asctime]s [%[levelname]s:%[module]s] %[message]s"] streamformat = logging.Formatter["%[asctime]s [%[levelname]s]: %[name]s: %[message]s"] stream.setLevel[logging.INFO] stream.setFormatter[streamformat] # Adding all handlers to the logs logger.addHandler[file] logger.addHandler[stream] def logger_cleanup[path, days_to_keep]: lclogger = logging.getLogger[__name__] logpath = f"{path}" now = time.time[] for filename in os.listdir[logpath]: filestamp = os.stat[os.path.join[logpath, filename]].st_mtime filecompare = now - days_to_keep * 86400 if filestamp < filecompare: lclogger.info["Delete old log " + filename] try: os.remove[os.path.join[logpath, filename]] except Exception as e: lclogger.exception[e] continue
- Tại thời điểm này, tôi không muốn sử dụng
1 hoặc## my_logger.py from datetime import datetime import time import os ## Init logging start import logging import logging.handlers def logger_init[]: print["print in my_logger.logger_init[]"] print["print my_logger.py __name__: " +__name__] path = "log/" filename = "my_log_test.log" ## get logger #logger = logging.getLogger[__name__] ## this was my mistake, to init a module logger here logger = logging.getLogger[] ## root logger logger.setLevel[logging.INFO] # File handler logfilename = datetime.now[].strftime["%Y%m%d_%H%M%S"] + f"_{filename}" file = logging.handlers.TimedRotatingFileHandler[f"{path}{logfilename}", when="midnight", interval=1] #fileformat = logging.Formatter["%[asctime]s [%[levelname]s] %[message]s"] fileformat = logging.Formatter["%[asctime]s [%[levelname]s]: %[name]s: %[message]s"] file.setLevel[logging.INFO] file.setFormatter[fileformat] # Stream handler stream = logging.StreamHandler[] #streamformat = logging.Formatter["%[asctime]s [%[levelname]s:%[module]s] %[message]s"] streamformat = logging.Formatter["%[asctime]s [%[levelname]s]: %[name]s: %[message]s"] stream.setLevel[logging.INFO] stream.setFormatter[streamformat] # Adding all handlers to the logs logger.addHandler[file] logger.addHandler[stream] def logger_cleanup[path, days_to_keep]: lclogger = logging.getLogger[__name__] logpath = f"{path}" now = time.time[] for filename in os.listdir[logpath]: filestamp = os.stat[os.path.join[logpath, filename]].st_mtime filecompare = now - days_to_keep * 86400 if filestamp < filecompare: lclogger.info["Delete old log " + filename] try: os.remove[os.path.join[logpath, filename]] except Exception as e: lclogger.exception[e] continue
2 nhưng giữ nó như trong cuốn sách nấu ăn ghi nhật kýlogging cookbook## my_logger.py from datetime import datetime import time import os ## Init logging start import logging import logging.handlers def logger_init[]: print["print in my_logger.logger_init[]"] print["print my_logger.py __name__: " +__name__] path = "log/" filename = "my_log_test.log" ## get logger #logger = logging.getLogger[__name__] ## this was my mistake, to init a module logger here logger = logging.getLogger[] ## root logger logger.setLevel[logging.INFO] # File handler logfilename = datetime.now[].strftime["%Y%m%d_%H%M%S"] + f"_{filename}" file = logging.handlers.TimedRotatingFileHandler[f"{path}{logfilename}", when="midnight", interval=1] #fileformat = logging.Formatter["%[asctime]s [%[levelname]s] %[message]s"] fileformat = logging.Formatter["%[asctime]s [%[levelname]s]: %[name]s: %[message]s"] file.setLevel[logging.INFO] file.setFormatter[fileformat] # Stream handler stream = logging.StreamHandler[] #streamformat = logging.Formatter["%[asctime]s [%[levelname]s:%[module]s] %[message]s"] streamformat = logging.Formatter["%[asctime]s [%[levelname]s]: %[name]s: %[message]s"] stream.setLevel[logging.INFO] stream.setFormatter[streamformat] # Adding all handlers to the logs logger.addHandler[file] logger.addHandler[stream] def logger_cleanup[path, days_to_keep]: lclogger = logging.getLogger[__name__] logpath = f"{path}" now = time.time[] for filename in os.listdir[logpath]: filestamp = os.stat[os.path.join[logpath, filename]].st_mtime filecompare = now - days_to_keep * 86400 if filestamp < filecompare: lclogger.info["Delete old log " + filename] try: os.remove[os.path.join[logpath, filename]] except Exception as e: lclogger.exception[e] continue
Vì vậy, về cơ bản, điều đó có nghĩa là, tôi cần khởi tạo bộ ghi gốc trong daemon.py
[luôn luôn] và trong các mô -đun mod1.py
và
## my_logger.py
from datetime import datetime
import time
import os
## Init logging start
import logging
import logging.handlers
def logger_init[]:
print["print in my_logger.logger_init[]"]
print["print my_logger.py __name__: " +__name__]
path = "log/"
filename = "my_log_test.log"
## get logger
#logger = logging.getLogger[__name__] ## this was my mistake, to init a module logger here
logger = logging.getLogger[] ## root logger
logger.setLevel[logging.INFO]
# File handler
logfilename = datetime.now[].strftime["%Y%m%d_%H%M%S"] + f"_{filename}"
file = logging.handlers.TimedRotatingFileHandler[f"{path}{logfilename}", when="midnight", interval=1]
#fileformat = logging.Formatter["%[asctime]s [%[levelname]s] %[message]s"]
fileformat = logging.Formatter["%[asctime]s [%[levelname]s]: %[name]s: %[message]s"]
file.setLevel[logging.INFO]
file.setFormatter[fileformat]
# Stream handler
stream = logging.StreamHandler[]
#streamformat = logging.Formatter["%[asctime]s [%[levelname]s:%[module]s] %[message]s"]
streamformat = logging.Formatter["%[asctime]s [%[levelname]s]: %[name]s: %[message]s"]
stream.setLevel[logging.INFO]
stream.setFormatter[streamformat]
# Adding all handlers to the logs
logger.addHandler[file]
logger.addHandler[stream]
def logger_cleanup[path, days_to_keep]:
lclogger = logging.getLogger[__name__]
logpath = f"{path}"
now = time.time[]
for filename in os.listdir[logpath]:
filestamp = os.stat[os.path.join[logpath, filename]].st_mtime
filecompare = now - days_to_keep * 86400
if filestamp < filecompare:
lclogger.info["Delete old log " + filename]
try:
os.remove[os.path.join[logpath, filename]]
except Exception as e:
lclogger.exception[e]
continue
0 [chỉ khi gọi trực tiếp chúng].root logger in daemon.py
[always]
and in the modules mod1.py
and ## my_logger.py
from datetime import datetime
import time
import os
## Init logging start
import logging
import logging.handlers
def logger_init[]:
print["print in my_logger.logger_init[]"]
print["print my_logger.py __name__: " +__name__]
path = "log/"
filename = "my_log_test.log"
## get logger
#logger = logging.getLogger[__name__] ## this was my mistake, to init a module logger here
logger = logging.getLogger[] ## root logger
logger.setLevel[logging.INFO]
# File handler
logfilename = datetime.now[].strftime["%Y%m%d_%H%M%S"] + f"_{filename}"
file = logging.handlers.TimedRotatingFileHandler[f"{path}{logfilename}", when="midnight", interval=1]
#fileformat = logging.Formatter["%[asctime]s [%[levelname]s] %[message]s"]
fileformat = logging.Formatter["%[asctime]s [%[levelname]s]: %[name]s: %[message]s"]
file.setLevel[logging.INFO]
file.setFormatter[fileformat]
# Stream handler
stream = logging.StreamHandler[]
#streamformat = logging.Formatter["%[asctime]s [%[levelname]s:%[module]s] %[message]s"]
streamformat = logging.Formatter["%[asctime]s [%[levelname]s]: %[name]s: %[message]s"]
stream.setLevel[logging.INFO]
stream.setFormatter[streamformat]
# Adding all handlers to the logs
logger.addHandler[file]
logger.addHandler[stream]
def logger_cleanup[path, days_to_keep]:
lclogger = logging.getLogger[__name__]
logpath = f"{path}"
now = time.time[]
for filename in os.listdir[logpath]:
filestamp = os.stat[os.path.join[logpath, filename]].st_mtime
filecompare = now - days_to_keep * 86400
if filestamp < filecompare:
lclogger.info["Delete old log " + filename]
try:
os.remove[os.path.join[logpath, filename]]
except Exception as e:
lclogger.exception[e]
continue
0 [only when calling them directly].Để làm cho init này trong một số mô -đun dễ dàng hơn, tôi đã tạo
## my_logger.py
from datetime import datetime
import time
import os
## Init logging start
import logging
import logging.handlers
def logger_init[]:
print["print in my_logger.logger_init[]"]
print["print my_logger.py __name__: " +__name__]
path = "log/"
filename = "my_log_test.log"
## get logger
#logger = logging.getLogger[__name__] ## this was my mistake, to init a module logger here
logger = logging.getLogger[] ## root logger
logger.setLevel[logging.INFO]
# File handler
logfilename = datetime.now[].strftime["%Y%m%d_%H%M%S"] + f"_{filename}"
file = logging.handlers.TimedRotatingFileHandler[f"{path}{logfilename}", when="midnight", interval=1]
#fileformat = logging.Formatter["%[asctime]s [%[levelname]s] %[message]s"]
fileformat = logging.Formatter["%[asctime]s [%[levelname]s]: %[name]s: %[message]s"]
file.setLevel[logging.INFO]
file.setFormatter[fileformat]
# Stream handler
stream = logging.StreamHandler[]
#streamformat = logging.Formatter["%[asctime]s [%[levelname]s:%[module]s] %[message]s"]
streamformat = logging.Formatter["%[asctime]s [%[levelname]s]: %[name]s: %[message]s"]
stream.setLevel[logging.INFO]
stream.setFormatter[streamformat]
# Adding all handlers to the logs
logger.addHandler[file]
logger.addHandler[stream]
def logger_cleanup[path, days_to_keep]:
lclogger = logging.getLogger[__name__]
logpath = f"{path}"
now = time.time[]
for filename in os.listdir[logpath]:
filestamp = os.stat[os.path.join[logpath, filename]].st_mtime
filecompare = now - days_to_keep * 86400
if filestamp < filecompare:
lclogger.info["Delete old log " + filename]
try:
os.remove[os.path.join[logpath, filename]]
except Exception as e:
lclogger.exception[e]
continue
6, những gì được mô tả trong sách nấu ăn.Sai lầm của tôi
Trước đó, sai lầm của tôi trong mô -đun đó là khởi động logger với
## my_logger.py
from datetime import datetime
import time
import os
## Init logging start
import logging
import logging.handlers
def logger_init[]:
print["print in my_logger.logger_init[]"]
print["print my_logger.py __name__: " +__name__]
path = "log/"
filename = "my_log_test.log"
## get logger
#logger = logging.getLogger[__name__] ## this was my mistake, to init a module logger here
logger = logging.getLogger[] ## root logger
logger.setLevel[logging.INFO]
# File handler
logfilename = datetime.now[].strftime["%Y%m%d_%H%M%S"] + f"_{filename}"
file = logging.handlers.TimedRotatingFileHandler[f"{path}{logfilename}", when="midnight", interval=1]
#fileformat = logging.Formatter["%[asctime]s [%[levelname]s] %[message]s"]
fileformat = logging.Formatter["%[asctime]s [%[levelname]s]: %[name]s: %[message]s"]
file.setLevel[logging.INFO]
file.setFormatter[fileformat]
# Stream handler
stream = logging.StreamHandler[]
#streamformat = logging.Formatter["%[asctime]s [%[levelname]s:%[module]s] %[message]s"]
streamformat = logging.Formatter["%[asctime]s [%[levelname]s]: %[name]s: %[message]s"]
stream.setLevel[logging.INFO]
stream.setFormatter[streamformat]
# Adding all handlers to the logs
logger.addHandler[file]
logger.addHandler[stream]
def logger_cleanup[path, days_to_keep]:
lclogger = logging.getLogger[__name__]
logpath = f"{path}"
now = time.time[]
for filename in os.listdir[logpath]:
filestamp = os.stat[os.path.join[logpath, filename]].st_mtime
filecompare = now - days_to_keep * 86400
if filestamp < filecompare:
lclogger.info["Delete old log " + filename]
try:
os.remove[os.path.join[logpath, filename]]
except Exception as e:
lclogger.exception[e]
continue
7 [logger mô -đun] thay vì sử dụng ## my_logger.py
from datetime import datetime
import time
import os
## Init logging start
import logging
import logging.handlers
def logger_init[]:
print["print in my_logger.logger_init[]"]
print["print my_logger.py __name__: " +__name__]
path = "log/"
filename = "my_log_test.log"
## get logger
#logger = logging.getLogger[__name__] ## this was my mistake, to init a module logger here
logger = logging.getLogger[] ## root logger
logger.setLevel[logging.INFO]
# File handler
logfilename = datetime.now[].strftime["%Y%m%d_%H%M%S"] + f"_{filename}"
file = logging.handlers.TimedRotatingFileHandler[f"{path}{logfilename}", when="midnight", interval=1]
#fileformat = logging.Formatter["%[asctime]s [%[levelname]s] %[message]s"]
fileformat = logging.Formatter["%[asctime]s [%[levelname]s]: %[name]s: %[message]s"]
file.setLevel[logging.INFO]
file.setFormatter[fileformat]
# Stream handler
stream = logging.StreamHandler[]
#streamformat = logging.Formatter["%[asctime]s [%[levelname]s:%[module]s] %[message]s"]
streamformat = logging.Formatter["%[asctime]s [%[levelname]s]: %[name]s: %[message]s"]
stream.setLevel[logging.INFO]
stream.setFormatter[streamformat]
# Adding all handlers to the logs
logger.addHandler[file]
logger.addHandler[stream]
def logger_cleanup[path, days_to_keep]:
lclogger = logging.getLogger[__name__]
logpath = f"{path}"
now = time.time[]
for filename in os.listdir[logpath]:
filestamp = os.stat[os.path.join[logpath, filename]].st_mtime
filecompare = now - days_to_keep * 86400
if filestamp < filecompare:
lclogger.info["Delete old log " + filename]
try:
os.remove[os.path.join[logpath, filename]]
except Exception as e:
lclogger.exception[e]
continue
8 [để lấy logger gốc].root logger].Vấn đề đầu tiên là, khi được gọi từ daemon.py
, không gian tên của logger đã được đặt thành
## __main__.py
from my_log_test import daemon
if __name__ == '__main__':
print["print in __main__.py"]
daemon.run[]
0. Do đó, bộ ghi mô -đun trong mod1.py
với không gian tên "chưa từng có" ## __main__.py
from my_log_test import daemon
if __name__ == '__main__':
print["print in __main__.py"]
daemon.run[]
2 do đó không gắn vào logger khác và tôi sẽ không thấy đầu ra nhật ký từ Mod1."Vấn đề" thứ hai là, chương trình chính của tôi là ở daemon.py
chứ không phải trong __main__.py
. Nhưng sau tất cả không phải là một vấn đề thực sự đối với tôi, nhưng nó đã thêm vào sự nhầm lẫn không gian tên.
Giải pháp làm việc
Đây là từ sách nấu ăn nhưng trong một mô -đun riêng biệt. Tôi cũng đã thêm một hàm
## __main__.py
from my_log_test import daemon
if __name__ == '__main__':
print["print in __main__.py"]
daemon.run[]
5 mà tôi có thể gọi từ daemon, để xóa nhật ký cũ hơn x ngày.## my_logger.py
from datetime import datetime
import time
import os
## Init logging start
import logging
import logging.handlers
def logger_init[]:
print["print in my_logger.logger_init[]"]
print["print my_logger.py __name__: " +__name__]
path = "log/"
filename = "my_log_test.log"
## get logger
#logger = logging.getLogger[__name__] ## this was my mistake, to init a module logger here
logger = logging.getLogger[] ## root logger
logger.setLevel[logging.INFO]
# File handler
logfilename = datetime.now[].strftime["%Y%m%d_%H%M%S"] + f"_{filename}"
file = logging.handlers.TimedRotatingFileHandler[f"{path}{logfilename}", when="midnight", interval=1]
#fileformat = logging.Formatter["%[asctime]s [%[levelname]s] %[message]s"]
fileformat = logging.Formatter["%[asctime]s [%[levelname]s]: %[name]s: %[message]s"]
file.setLevel[logging.INFO]
file.setFormatter[fileformat]
# Stream handler
stream = logging.StreamHandler[]
#streamformat = logging.Formatter["%[asctime]s [%[levelname]s:%[module]s] %[message]s"]
streamformat = logging.Formatter["%[asctime]s [%[levelname]s]: %[name]s: %[message]s"]
stream.setLevel[logging.INFO]
stream.setFormatter[streamformat]
# Adding all handlers to the logs
logger.addHandler[file]
logger.addHandler[stream]
def logger_cleanup[path, days_to_keep]:
lclogger = logging.getLogger[__name__]
logpath = f"{path}"
now = time.time[]
for filename in os.listdir[logpath]:
filestamp = os.stat[os.path.join[logpath, filename]].st_mtime
filecompare = now - days_to_keep * 86400
if filestamp < filecompare:
lclogger.info["Delete old log " + filename]
try:
os.remove[os.path.join[logpath, filename]]
except Exception as e:
lclogger.exception[e]
continue
Để chạy deamon.py [thông qua __main__.py
] sử dụng
## __main__.py
from my_log_test import daemon
if __name__ == '__main__':
print["print in __main__.py"]
daemon.run[]
7## __main__.py
from my_log_test import daemon
if __name__ == '__main__':
print["print in __main__.py"]
daemon.run[]
Để chạy deamon.py [trực tiếp] sử dụng
## __main__.py
from my_log_test import daemon
if __name__ == '__main__':
print["print in __main__.py"]
daemon.run[]
8## daemon.py
from datetime import datetime
import time
import logging
import my_log_test.pkg1.mod1 as mod1
import my_log_test.pkg2.mod2 as mod2
## init ROOT logger from my_logger.logger_init[]
from my_log_test.common.my_logger import logger_init
logger_init[] ## init root logger
logger = logging.getLogger[__name__] ## module logger
def run[]:
print["print in daemon.run[]"]
print["print daemon.py __name__: " +__name__]
logger.info["Start daemon"]
loop_count = 1
while True:
logger.info[f"loop_count: {loop_count}"]
logger.info["do stuff from pkg1"]
mod1.do1[]
logger.info["finished stuff from pkg1"]
logger.info["do stuff from pkg2"]
mod2.do2[]
logger.info["finished stuff from pkg2"]
logger.info["Waiting a bit..."]
time.sleep[30]
if __name__ == '__main__':
try:
print["print in daemon.py if __name__ == '__main__'"]
logger.info["running daemon.py as main"]
run[]
except KeyboardInterrupt as e:
logger.info["Program aborted by user"]
except Exception as e:
logger.info[e]
Để chạy mod1.py [trực tiếp] sử dụng
## __main__.py
from my_log_test import daemon
if __name__ == '__main__':
print["print in __main__.py"]
daemon.run[]
9## mod1.py
import logging
# mod1_logger = logging.getLogger[__name__]
mod1_logger = logging.getLogger["my_log_test.daemon.pkg1.mod1"] ## for testing, namespace set manually
def do1[]:
print["print in mod1.do1[]"]
print["print mod1.py __name__: " +__name__]
mod1_logger.info["Doing someting in pkg1.do1[]"]
if __name__ == '__main__':
## Also enable this pkg to be run directly while in development with
## python3 -m my_log_test.pkg1.mod1
## init root logger
from my_log_test.common.my_logger import logger_init
logger_init[] ## init root logger
print["print in mod1.py if __name__ == '__main__'"]
mod1_logger.info["Running mod1.py as main"]
do1[]
Để chạy mod2.py [trực tiếp] sử dụng
## daemon.py
from datetime import datetime
import time
import logging
import my_log_test.pkg1.mod1 as mod1
import my_log_test.pkg2.mod2 as mod2
## init ROOT logger from my_logger.logger_init[]
from my_log_test.common.my_logger import logger_init
logger_init[] ## init root logger
logger = logging.getLogger[__name__] ## module logger
def run[]:
print["print in daemon.run[]"]
print["print daemon.py __name__: " +__name__]
logger.info["Start daemon"]
loop_count = 1
while True:
logger.info[f"loop_count: {loop_count}"]
logger.info["do stuff from pkg1"]
mod1.do1[]
logger.info["finished stuff from pkg1"]
logger.info["do stuff from pkg2"]
mod2.do2[]
logger.info["finished stuff from pkg2"]
logger.info["Waiting a bit..."]
time.sleep[30]
if __name__ == '__main__':
try:
print["print in daemon.py if __name__ == '__main__'"]
logger.info["running daemon.py as main"]
run[]
except KeyboardInterrupt as e:
logger.info["Program aborted by user"]
except Exception as e:
logger.info[e]
0## mod2.py
import logging
logger = logging.getLogger[__name__]
def do2[]:
print["print in pkg2.do2[]"]
print["print mod2.py __name__: " +__name__] # setting namespace through __name__
logger.info["Doing someting in pkg2.do2[]"]
if __name__ == '__main__':
## Also enable this pkg to be run directly while in development with
## python3 -m my_log_test.pkg2.mod2
## init root logger
from my_log_test.common.my_logger import logger_init
logger_init[] ## init root logger
print["print in mod2.py if __name__ == '__main__'"]
logger.info["Running mod2.py as main"]
do2[]
Hạnh phúc nếu nó giúp. Rất vui khi nhận được phản hồi là tốt!