Python 异常处理与日志记录

👽发现宝藏

前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。【点击进入巨牛的人工智能学习网站】。

异常处理是任何编程语言中的重要组成部分,Python 也不例外。Python 提供了丰富的异常处理机制,让开发者可以更好地管理程序中出现的错误。除了捕获和处理异常外,记录异常信息也是至关重要的,以便日后排查问题和改进程序。本文将介绍如何在 Python 中捕获异常,并将异常信息记录到日志文件中。

异常处理

在 Python 中,使用 try-except 语句来捕获异常。try 代码块中放置可能引发异常的代码,except 代码块中处理异常情况。

try:# 可能引发异常的代码result = 10 / 0
except ZeroDivisionError as e:# 处理异常情况print("除零错误发生:", e)

在上面的例子中,当除以零时会触发 ZeroDivisionError 异常,except 代码块会捕获这个异常并进行处理。

异常日志记录

除了简单地在控制台打印异常信息,我们还可以将异常信息记录到日志文件中,以便后续分析。Python 提供了内置的 logging 模块,可以轻松实现这一功能。

import logging# 配置日志记录器
logging.basicConfig(filename='error.log', level=logging.ERROR)try:result = 10 / 0
except ZeroDivisionError as e:# 记录异常信息到日志文件logging.error("除零错误发生: %s", e)

在上述代码中,我们首先通过 basicConfig 方法配置了日志记录器,指定了日志文件名为 error.log,并设置记录级别为 ERROR,这意味着只有 ERROR 级别及以上的日志才会被记录。然后,在 except 代码块中,我们使用 logging.error 方法将异常信息记录到日志文件中。

日志文件分析

通过记录异常信息到日志文件,我们可以随时查看程序运行中出现的异常情况,以便及时定位和解决问题。可以使用文本编辑器或日志分析工具来查看日志文件内容,分析异常发生的原因和频率。

error.log:ERROR:root:除零错误发生: division by zero

上述日志文件记录了一条除零错误的异常信息,其中包含了异常类型和具体错误信息。通过分析日志文件,我们可以清晰地了解到程序中存在的问题,并采取相应的措施进行修复。

高级日志记录配置

除了基本的日志记录配置外,logging 模块还提供了更多高级的配置选项,以满足不同场景下的需求。

1. 添加时间戳

可以通过配置 format 参数来添加时间戳到日志记录中,以便更好地跟踪异常发生的时间。

import logginglogging.basicConfig(filename='error.log', level=logging.ERROR, format='%(asctime)s - %(levelname)s - %(message)s')
2. 指定日志格式

可以通过配置 format 参数来指定日志的格式,以便更清晰地展示异常信息。

import logginglogging.basicConfig(filename='error.log', level=logging.ERROR, format='%(asctime)s - %(levelname)s - %(message)s - %(filename)s:%(lineno)d')
3. 添加异常堆栈信息

可以通过设置 exc_info 参数为 True 来添加异常的堆栈信息到日志记录中。

import loggingtry:result = 10 / 0
except ZeroDivisionError as e:logging.error("除零错误发生: %s", e, exc_info=True)
4. 日志分级

除了 ERROR 级别外,logging 模块还支持其他几种日志级别,包括 DEBUG、INFO、WARNING、CRITICAL 等。可以根据实际需求选择合适的日志级别进行记录。

import logginglogging.basicConfig(filename='app.log', level=logging.DEBUG)

日志轮换与归档

对于大型项目或长期运行的程序,日志文件可能会变得非常庞大。为了解决这个问题,logging 模块支持日志轮换和归档功能,可以按照一定的策略将日志文件分割、压缩或移动到其他位置。

import logging
from logging.handlers import RotatingFileHandlerhandler = RotatingFileHandler('app.log', maxBytes=10000, backupCount=5)
handler.setLevel(logging.DEBUG)
formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s')
handler.setFormatter(formatter)logger = logging.getLogger(__name__)
logger.addHandler(handler)logger.debug('This is a debug message')

在上述代码中,我们使用 RotatingFileHandler 类来实现日志轮换功能,设置了日志文件的最大字节数为 10000 字节,备份文件的数量为 5。当日志文件大小超过设定的最大字节数时,会自动创建新的日志文件,并将旧的日志文件备份。

日志配置文件

在较大的项目中,可能需要更加灵活和复杂的日志配置。为了避免在代码中硬编码日志配置,可以将日志配置信息单独存放在一个配置文件中,例如 logging.conf

[loggers]
keys=root[handlers]
keys=fileHandler[formatters]
keys=myFormatter[logger_root]
level=DEBUG
handlers=fileHandler[handler_fileHandler]
class=FileHandler
level=DEBUG
formatter=myFormatter
args=('app.log',)[formatter_myFormatter]
format=%(asctime)s - %(levelname)s - %(message)s

然后在 Python 代码中使用 logging.config 模块加载配置文件。

import logging
import logging.configlogging.config.fileConfig('logging.conf')logger = logging.getLogger(__name__)
logger.debug('This is a debug message')

异常链追踪

有时候,程序中的异常不仅仅是由当前位置的代码引发的,可能还涉及到调用栈上的其他函数或模块。为了更好地追踪异常的来源,可以使用 logging.exception 方法来记录异常链。

import loggingtry:result = 10 / 0
except ZeroDivisionError as e:logging.exception("除零错误发生")

上述代码会将当前异常以及调用栈上的所有异常信息记录到日志中,方便后续排查问题。

异常处理装饰器

为了简化异常处理的代码,可以定义一个异常处理的装饰器,统一处理函数中的异常情况。

import logging
from functools import wrapsdef handle_exceptions(logger):def decorator(func):@wraps(func)def wrapper(*args, **kwargs):try:return func(*args, **kwargs)except Exception as e:logger.exception("异常发生: %s", e)return wrapperreturn decoratorlogger = logging.getLogger(__name__)@handle_exceptions(logger)
def divide(x, y):return x / yresult = divide(10, 0)

上述代码定义了一个名为 handle_exceptions 的装饰器,可以将函数中的异常信息记录到日志中。然后,我们将 divide 函数应用了该装饰器,即使在函数内部发生异常,也会被捕获并记录到日志中。

日志记录的性能考虑

在实际项目中,日志记录的性能也是需要考虑的重要因素。过于频繁或过度详细的日志记录可能会对程序的性能产生负面影响,因此需要在记录足够信息的同时,尽量减少对性能的影响。

1. 日志级别控制

在配置日志记录器时,可以根据不同的场景和需求设置不同的日志级别。在开发和测试阶段,可以设置为 DEBUG 级别以记录更详细的信息,而在生产环境中,可以设置为 WARNING 或更高级别以减少日志记录的数量,从而降低对性能的影响。

import logginglogging.basicConfig(level=logging.DEBUG)  # 开发/测试环境
# logging.basicConfig(level=logging.WARNING)  # 生产环境
2. 异步日志记录

为了减少日志记录对主程序的阻塞,可以使用异步日志记录器,将日志记录操作放到独立的线程或进程中执行,从而提高程序的响应速度。

import logging
import logging.handlerslogger = logging.getLogger(__name__)
handler = logging.handlers.QueueHandler()
logger.addHandler(handler)queue = logging.handlers.QueueListener(handler, *logger.handlers)
queue.start()
3. 批量写入

在高并发环境中,频繁地向日志文件写入可能会导致文件 I/O 压力过大,影响系统性能。为了解决这个问题,可以考虑将日志记录操作改为批量写入,例如使用队列缓存日志消息,然后定期将队列中的消息批量写入日志文件。

import logging
import queue
import threadinglog_queue = queue.Queue()def log_worker():while True:record = log_queue.get()logger = logging.getLogger(record.name)logger.handle(record)log_queue.task_done()thread = threading.Thread(target=log_worker, daemon=True)
thread.start()logging.basicConfig(level=logging.INFO)
logging.handlers.QueueHandler(log_queue)

日志记录的安全性考虑

除了性能和功能需求外,日志记录的安全性也是需要考虑的重要因素。在实际项目中,可能存在一些敏感信息需要记录,如用户密码、API 密钥等,如果不加以保护,可能会造成信息泄露和安全漏洞。

1. 敏感信息过滤

在记录日志时,应当避免将敏感信息直接记录到日志中,尤其是在生产环境中。可以通过过滤器来检查日志消息,将其中的敏感信息进行替换或删除。

import loggingclass SensitiveFilter(logging.Filter):def filter(self, record):record.msg = record.msg.replace('password', '***')return Truelogger = logging.getLogger(__name__)
logger.addFilter(SensitiveFilter())
2. 安全存储

日志文件本身可能包含敏感信息,因此需要采取相应的安全措施来保护日志文件的安全性。可以将日志文件存储在受限制的访问路径下,设置合适的文件权限,以及定期清理和归档日志文件。

import logginglogging.basicConfig(filename='/var/log/app.log', level=logging.INFO)
3. 加密传输

如果日志信息需要通过网络传输,应当采取加密的方式来保护数据的安全性,防止被中间人窃取或篡改。可以使用 TLS/SSL 协议来加密日志传输通道。

import logging
import logging.handlershandler = logging.handlers.SysLogHandler(address=('localhost', 514))
handler.socktype = socket.SOCK_STREAM
handler.ssl_context = ssl.create_default_context()logger = logging.getLogger(__name__)
logger.addHandler(handler)

日志记录审计

除了安全性考虑外,日志记录还可以用于审计目的,帮助监控系统的运行情况、用户行为和操作记录,以及追踪安全事件和异常情况。通过分析日志记录,可以及时发现潜在的安全威胁和漏洞,并采取相应的措施进行预防和应对。

import logginglogging.basicConfig(filename='audit.log', level=logging.INFO)def audit_log(func):def wrapper(*args, **kwargs):result = func(*args, **kwargs)logging.info(f'{func.__name__} called with arguments: {args}, {kwargs}. Result: {result}')return resultreturn wrapper@audit_log
def add(x, y):return x + yadd(3, 4)

在上述代码中,我们定义了一个名为 audit_log 的装饰器,用于记录函数调用的参数和结果到审计日志文件中。通过对关键操作和敏感函数应用该装饰器,可以实现对系统行为的全面监控和审计。

日志监控和警报

除了记录日志和审计功能外,日志监控和警报也是关键的安全实践。通过监控日志文件的变化、异常和异常频率,可以及时发现系统中的异常行为和安全威胁,从而采取相应的措施进行响应和修复。

1. 实时监控

使用监控工具或脚本定期扫描日志文件,监控日志文件的变化和异常情况,及时发现和处理异常事件。

import os
import timelogfile = '/var/log/app.log'def monitor_logfile(logfile):while True:with open(logfile, 'r') as f:f.seek(0, os.SEEK_END)new_data = f.read()if new_data:print("发现新日志:", new_data)time.sleep(10)monitor_logfile(logfile)
2. 异常警报

当发现异常日志时,可以通过发送警报通知管理员或安全团队,以便及时响应和处理。

import smtplib
from email.mime.text import MIMETextdef send_alert(subject, message):sender_email = "your_email@example.com"receiver_email = "admin@example.com"password = "your_email_password"msg = MIMEText(message)msg['Subject'] = subjectmsg['From'] = sender_emailmsg['To'] = receiver_emailserver = smtplib.SMTP('smtp.example.com', 587)server.starttls()server.login(sender_email, password)server.sendmail(sender_email, receiver_email, msg.as_string())server.quit()# 在发现异常时调用 send_alert 函数发送邮件警报
3. 日志分析

使用日志分析工具或脚本对日志文件进行分析,识别异常行为、异常模式和安全事件,以及监控系统运行状态和性能表现。

import redef analyze_logfile(logfile):pattern = r'ERROR|WARNING'with open(logfile, 'r') as f:for line in f:if re.search(pattern, line):print("发现异常日志:", line)analyze_logfile(logfile)

自动化响应

为了进一步提高安全性和响应速度,可以将日志监控和警报的流程自动化,通过脚本或自动化工具来自动检测、警报和响应异常事件。

import subprocessdef automate_response(logfile):pattern = r'ERROR|WARNING'result = subprocess.run(['grep', '-E', pattern, logfile], capture_output=True)if result.stdout:send_alert("发现异常日志", result.stdout.decode())automate_response(logfile)

日志备份和恢复

除了监控和警报外,日志备份和恢复也是关键的安全实践。定期备份日志文件可以防止日志丢失或被篡改,同时在需要时可以快速恢复到历史状态,帮助排查问题和恢复系统功能。

1. 定期备份

使用定时任务或脚本定期备份日志文件,将当前日志文件复制到备份目录或存储介质中,以确保日志数据的安全性和可靠性。

import shutil
import timedef backup_logfile(logfile, backup_dir):timestamp = time.strftime('%Y%m%d%H%M%S')backup_file = f'{backup_dir}/app_{timestamp}.log'shutil.copy(logfile, backup_file)
2. 日志归档

对于长期运行的系统,日志文件可能会变得非常庞大,为了节省存储空间和提高检索效率,可以定期对日志文件进行归档,将旧的日志文件压缩或移动到归档目录中。

import os
import shutil
import zipfiledef archive_logfile(logfile, archive_dir):if os.path.exists(logfile):shutil.move(logfile, archive_dir)with zipfile.ZipFile(f'{archive_dir}/app_logs.zip', 'w') as zipf:zipf.write(f'{archive_dir}/app.log', arcname='app.log')
3. 日志恢复

在需要恢复日志文件时,可以从备份或归档中找到对应的日志文件,并将其复制到原始位置进行恢复。

def restore_logfile(backup_file, original_file):shutil.copy(backup_file, original_file)

日志清理和管理

为了避免日志文件过大或占用过多存储空间,可以定期清理和管理日志文件,删除过期和不必要的日志数据,以保持系统的性能和稳定性。

import os
import globdef cleanup_logs(log_dir, max_age):current_time = time.time()for logfile in glob.glob(f'{log_dir}/*.log'):if os.path.getmtime(logfile) < current_time - max_age:os.remove(logfile)

日志文件加密和权限控制

除了备份和管理外,保护日志文件的安全性也是至关重要的。通过加密日志文件和限制文件权限,可以防止未授权访问和篡改,保障日志数据的保密性和完整性。

1. 文件加密

使用加密算法对日志文件进行加密,以确保日志数据在存储和传输过程中的安全性。可以使用加密库如 cryptography 来实现对日志文件的加密和解密操作。

from cryptography.fernet import Fernetdef encrypt_logfile(logfile, key):with open(logfile, 'rb') as f:data = f.read()fernet = Fernet(key)encrypted_data = fernet.encrypt(data)with open(logfile + '.enc', 'wb') as f:f.write(encrypted_data)def decrypt_logfile(encrypted_file, key):with open(encrypted_file, 'rb') as f:encrypted_data = f.read()fernet = Fernet(key)decrypted_data = fernet.decrypt(encrypted_data)with open(encrypted_file[:-4], 'wb') as f:f.write(decrypted_data)
2. 文件权限控制

通过设置文件权限来限制对日志文件的访问权限,只允许授权用户或组访问和修改日志文件,防止未授权用户篡改或查看日志内容。

import osdef set_file_permissions(logfile, mode):os.chmod(logfile, mode)

日志访问审计

对于敏感信息和重要日志数据,应当实施严格的访问控制和审计机制,记录和监控对日志文件的访问和操作记录,及时发现和处理未授权的访问和异常行为。

import subprocessdef audit_log_access(logfile):result = subprocess.run(['ls', '-l', logfile], capture_output=True)print("日志文件权限信息:", result.stdout.decode())

结论

通过加密日志文件、限制文件权限和实施访问审计,可以有效保护日志数据的安全性和完整性,防止未授权访问和篡改,保障系统的安全运行和数据保护。

在实际项目中,建议结合加密库、操作系统权限控制和审计工具,建立完善的日志安全管理机制,以确保日志系统的安全性和可靠性。

希望本文的介绍能够帮助您更好地理解和应用日志文件加密和权限控制在实际项目中的重要性和作用。

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/827486.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

换脸插件升级导致SDWebUI无法启动cannot import name ‘Undefined‘ from ‘pydantic.fields‘

今天在一台新的机器环境装了SDWEBUI&#xff0c;都使用最新的版本&#xff0c;升级了下换脸的插件&#xff0c;于是乎启动崩溃了。错误如下 Launching Web UI with arguments: --listen --skip-torch-cuda-test --disable-nan-check --skip-version-check --skip-python-versi…

鸿蒙 harmonyos 线程 并发 总结 async promise Taskpool woker(三)多线程并发 Worker

Worker Worker是与主线程并行的独立线程。创建Worker的线程称之为宿主线程&#xff0c;Worker自身的线程称之为Worker线程。创建Worker传入的url文件在Worker线程中执行&#xff0c;可以处理耗时操作但不可以直接操作UI。 Worker主要作用是为应用程序提供一个多线程的运行环境…

kanzi工程辅助解析

背景:实际开发过程中&#xff0c;使用kanzi studio工程&#xff0c;遇到一个很大的问题&#xff0c;就是在多工程&#xff0c;多预设件&#xff0c;复杂绑定算式情况下&#xff0c;很难梳理接口绑定情况&#xff0c;而且kanzi自带的查找很不好用。尤其是拿到一个新工程&#xf…

春季打卡圣地|超出片的成都文创产业园

春季拍照还在去人民公园、青龙湖吗&#xff1f;这个春天来点不一样的&#xff0c;就在金牛区的成都文创产业园——国际数字影像产业园旁&#xff0c;沙河源公园占地面积约150亩&#xff0c;地下室面积约4000平方米&#xff0c;这里的花能让摄影爱好者们拍个够。 国际数字影像产…

FFmpeg源码编译

msys2 依赖环境安装 依赖环境安装编译X264编译 fdk-aac文件处理编译x265编译FFmpeg 依赖环境安装 编译X264 用于h264 AVC视频格式编码 CCcl ./configure --enable-shared #指定使用cl,编译成动态链接库 make -j32 #使用32线程进行编码 make install命令一 关于第一条命令执…

攻击者使用新型隐写术攻击,针对全球320个组织

隐写术是一种将数据隐藏在看似无害的文件中的技术&#xff0c;使用户和安全产品无法检测到它们。 近期&#xff0c;Positive Technologies 发现了TA558 黑客组织正在开展的一项新活动&#xff0c;使用隐写术将恶意代码隐藏在图像内&#xff0c;从而将各种恶意软件工具传递到目…

展会媒体邀约资源,媒体宣传服务执行

传媒如春雨&#xff0c;润物细无声&#xff0c;大家好&#xff0c;我是51媒体网胡老师。 在组织展会时&#xff0c;媒体宣传服务的执行是提升展会知名度和影响力的关键环节。 确定目标媒体&#xff1a;根据展会的主题和目标受众&#xff0c;选择适合的媒体进行邀请。这可能包…

docker 虚拟化与docker的概念

一、云计算的三种服务模式 laas、pass、saas 1.1 IaaS: Infrastructure-as-a-Service&#xff08;基础设施即服务&#xff09; 第一层叫做IaaS&#xff0c;有时候也叫做Hardware-as-a-Service&#xff0c;几年前如果你想在办公室或者公司的网站上运行一些企业应用&#xff0c…

将彩色图转化为灰度图及其原理介绍

彩色图介绍 彩色图像是一种包含颜色信息的图像&#xff0c;通常由红色、绿色和蓝色&#xff08;RGB&#xff09;三个颜色通道组成。这三种颜色通道可以叠加在一起来形成各种不同的颜色。 彩色图像中的每个像素都有三个数值&#xff0c;分别表示红色、绿色和蓝色通道的强度或亮…

vue 关键字变红

1.html <div v-html"replaceKeywordColor(item.title)" ></div> 2.js //value为搜索框内绑定的值 replaceKeywordColor(val) {if (val?.includes(this.value) && this.value ! ) {return val.replace(this.value,<font color"red&…

RuoYi-Vue-Plus (SaToken 注解鉴权)

一、SaInterceptor 注解鉴权和路由拦截鉴权 拦截器&#xff1a;SaInterceptor 实现类位置&#xff1a; cn.dev33.satoken.interceptor.SaInterceptor 功能&#xff1a;Sa-Token 综合拦截器&#xff0c;提供注解鉴权和路由拦截鉴权能力 /*** 创建一个 Sa-Token 综合拦截器&…

重学java 19.面向对象 继承 上

走不出的那段阴霾&#xff0c;很多时候只不过是&#xff0c;我们把它当成了唯一 —— 24.4.22 面向对象整体知识导向&#xff1a; 知识梳理&#xff1a; 1.知道继承的好处 2.会使用继承 3.继承之后成员变量和成员方法的访问特点 4.方法的重写&#xff0c;知道方法重写的使用场景…

从构成看自来水厂自动化控制系统的创新与发展

自来水厂自动化控制系统涵盖了多个关键组成部分&#xff0c;包括水管理云平台、供水监控系统以及供水调度平台。 系统内嵌了一系列自主创新的核心算法&#xff0c;这些算法结合了数学建模、机器仿真和流体力学等多元数据模型&#xff0c;以优化设备间的关联和控制关系&#xf…

python爬虫 - 爬取html中的script数据(爬取新闻 36kr.com)

文章目录 1. 分析页面内容数据格式2. 使用re.findall方法&#xff0c;爬取新闻3. 使用re.search 方法&#xff0c;爬取新闻 1. 分析页面内容数据格式 打开 https://36kr.com/ 按F12&#xff08;或 在网页上右键 --> 检查&#xff08;Inspect&#xff09;&#xff09; 找…

大珩PPT助手一键颜色设置

大珩PPT助手最新推出的一键设置文字颜色和背景色功能&#xff0c;为用户在创建演示文稿时带来了更便捷、高效的体验。这一功能使用户能够轻松调整演示文稿中文字的颜色和幻灯片的背景色&#xff0c;以满足不同场合和主题的需要。 以下是该功能的几个关键特点和优势&#xff1a…

2024深圳杯东三省数学建模竞赛A题个火箭残骸的准确定位代码成品论文

问题重述 绝大多数火箭为多级火箭&#xff0c;下面级火箭或助推器完成既定任务后&#xff0c;通过级间分离装置分离后坠落。在坠落至地面过程中&#xff0c;残骸会产生跨音速音爆。为了快速回收火箭残骸&#xff0c;在残骸理论落区内布置多台震动波监测设备&#xff0c;以接收不…

账号安全基本措施2

sudo命令 sudo(superuser do)&#xff0c;允许系统管理员让普通用户执行一些或者全部的root命令的一个工具。 其配置在/etc/sudoers权。它允许系统管理员集中的管理用户的使用权限和使用的主机。属性必须为0440。 语法检查&#xff1a; 检查语法&#xff1a; 修改文件时&…

刷课必备!用Python实现网上自动做题

前言 开学少不了老师会布置一些 软件上面的作业&#xff0c;今天教大家用python制作自动答题脚本&#xff0c;100%准确率哦喜欢的同学记得关注、收藏哦 环境使用 Python3.8Pycharm 模块使用 import requests —> 数据请求模块 pip install requestsimport parsel —>…

【Qt 学习笔记】Qt常用控件 | 显示类控件 | Calendar Widget的使用及说明

博客主页&#xff1a;Duck Bro 博客主页系列专栏&#xff1a;Qt 专栏关注博主&#xff0c;后期持续更新系列文章如果有错误感谢请大家批评指出&#xff0c;及时修改感谢大家点赞&#x1f44d;收藏⭐评论✍ Qt常用控件 | 显示类控件 | Calendar Widget的使用及说明 文章编号&am…

基于STM32实现流水灯【Proteus仿真】

详情更多 wechat&#xff1a;嵌入式工程师成长日记 https://mp.weixin.qq.com/s?__bizMzg4Mzc3NDUxOQ&mid2247485624&idx1&sn4e553234c2624777409bd2067a07aad8&chksmcf430de0f83484f6189b119d9d83ea6e6f2a85d13afaa04d218483918231c38e6382d3007061&tok…