在我的Flask应用程序中,我使用logging
库实现了一个日志记录系统。它当前在以下函数中运行:
if __name__ == "__main__":
"""[Runs the webserver.
Finally block is used for some logging management. It will first shut down
logging, to ensure no files are open, then renames the file to 'log_'
+ the current date, and finally moves the file to the /logs archive
directory]
"""
try:
session_management.clean_uploads_on_start(UPLOAD_FOLDER)
app.run(debug=False)
finally:
try:
logging.shutdown()
new_log_file_name = log_management.rename_log(app.config['DEFAULT_LOG_NAME'])
log_management.move_log(new_log_file_name)
except FileNotFoundError:
logging.warning("Current log file not found")
except PermissionError:
logging.warning("Permissions lacking to rename or move log.")
我发现,如果cmd提示符被强制关闭,或者服务器崩溃,文件不会被重命名和移动。我认为在服务器启动之前,最好将重命名和移动放在函数的初始“try”块中,但我遇到了问题,因为我有一个配置文件(在该脚本中导入),其中包含以下代码:
logging.basicConfig(filename='current_log.log', level=logging.INFO,
filemode='a',
format='%(asctime)s:%(levelname)s:%(message)s')
我尝试过做如下的事情,但仍然会遇到权限错误,但我认为仍然会遇到错误,因为日志管理脚本也会导入配置。此外,我找不到一个类似于logging.shutdown()的启动日志系统的函数,该函数在系统结束时使用,否则我会关闭它,移动文件(如果存在)并重新启动它
try:
session_management.clean_uploads_on_start(UPLOAD_FOLDER)
log_management.check_log_on_startup(app.config['DEFAULT_LOG_NAME'])
import config
app.run(debug=False)
finally:
try:
logging.shutdown()
new_log_file_name = log_management.rename_log(app.config['DEFAULT_LOG_NAME'])
log_management.move_log(new_log_file_name)
except FileNotFoundError:
logging.warning("Current log file not found")
except PermissionError:
logging.warning("Permissions lacking to rename or move log.")
# (in another script)
def check_log_on_startup(file_name):
if os.path.exists(file_name):
move_log(rename_log(file_name))
任何建议都很受欢迎,因为我感觉自己就像在一堵砖墙前
正如您已经发现的,如果流程不干净地终止,那么在流程生命周期结束时尝试执行清理可能会失败
在开始时执行清理的问题是,在尝试移动旧日志文件之前,您显然从导入中调用了
logging.basicConfig
这会导致在尝试重命名和移动现有日志时,隐式创建的FileHandler
在现有日志上保存一个打开的文件对象。根据您使用的文件系统的不同,这可能不会令人高兴如果您想将对可能的旧日志文件的处理完全移动到应用程序的开头,则必须在调用
logging.basicConfig
之前执行重命名和移动,因此您必须从导入中删除它并以某种方式将其添加到log_management
或者,您可以通过对标准
FileHandler
类进行子类化,将日志文件的整个处理过程移动到日志文件处理程序,例如:使用此选项,您可以如下配置日志记录:
CustomFileHandler
将在初始化期间检查并可能存档旧日志。这将处理不干净的流程终止后的遗留问题,其中无法进行关机清理。由于父类初始值设定项是在尝试日志存档后调用的,因此日志上还没有导致PermissionError
的打开句柄重写的
close()
方法将在干净的进程关闭时执行归档这应该消除对专用
log_management
模块的需要,至少就代码中显示的函数而言是这样rename_log
、move_log
和check_log_on_startup
都封装在CustomFileHandler
中。也不需要显式调用logging.shutdown()
一些注意事项:
找不到与} as exit handler 。} methods ,这将在干净关闭期间执行日志存档
logging.shutdown()
等效的启动函数的原因是,在导入logging
模块时,日志系统已启动/初始化。除其他外,它通过atexit实现instantiates the implicit root logger和registers ^{后者就是不需要用上述解决方案显式调用
logging.shutdown()
的原因。由于退出处理程序注册,Python解释器在准备解释器关闭时,将在完成过程中调用它logging.shutdown()
然后遍历已注册处理程序的列表和calls their ^{根据您选择的移动(和重命名)旧日志文件的方法,上述解决方案可能需要一些额外的异常保护措施^如果目标路径已经存在,{}将引发异常,即当您之前在同一天停止并启动了进程,而
os.replace
将以静默方式覆盖现有文件时。请参阅有关通过Pythonhere移动文件的更多详细信息因此,我建议不仅按当前日期,而且按时间命名存档日志。} 完成的,因此自定义文件处理程序的
在上面,将当前日期添加到存档文件名是通过
datetime
的^{archive_name
参数的默认值为“log{%Y%m%d”。前面带有%
的字符是有效的format codes,由strftime()
替换为调用它的datetime
对象的相应部分。要将当前时间附加到存档日志文件名,只需将相应的格式代码附加到archive_name
,例如:'log_%Y%m%d_strong>%H%m%S',这将产生一个日志名,如log_20200819_123721
相关问题 更多 >
编程相关推荐