28_python笔记-代码调试与测试

本文介绍多种调试方法,包括使用print函数、logging记录日志、PyCharm断点调试等,并讲解logging四大组件及日志轮转。此外,还介绍了pdb调试工具的使用方法以及单元测试的编写。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


个人博客
https://blog.youkuaiyun.com/cPen_web

#1.1 常用调试方法-print函数

示例

#使用 print 做调式
#有些信息是给开发人员看的,用户应该是无感知的
def func():
    r = input("请输入一个数字:")
    print(type(r))
    print(r)
    n = int(r)
    result = 100/n
    return result

print(func())

#2.1 常用调试方法-logging记日志

示例

#2.logging控制台输出
import logging

#设置默认输出日志等级
#打印DEBUG及以上日志
logging.basicConfig(level=logging.DEBUG, format = '%(asctime)s - %(pathname)s - %(levelname)s: %(message)s')

def func():
    r = input("请输入一个数字:")
    logging.debug(type(r))
    logging.debug(r)
    n = int(r)
    result = 100/n
    return result

print(func())
#结果为
# 请输入一个数字:1
# 100.0
# 2020-12-09 11:54:41,541 - E:/sanchuang/lianxi/31am.py - DEBUG: <class 'str'>
# 2020-12-09 11:54:41,541 - E:/sanchuang/lianxi/31am.py - DEBUG: 1

# %(levelno)s: 打印日志级别的数值
# %(levelname)s: 打印日志级别名称
# %(pathname)s: 打印当前执行程序的路径,其实就是sys.argv[0]
# %(filename)s: 打印当前执行程序名,python如:login.py
# %(funcName)s: 打印日志的当前函数
# %(lineno)d: 打印日志的当前行号,在第几行打印的日志
# %(asctime)s: 打印日志的时间
# %(thread)d: 打印线程ID
# %(threadName)s: 打印线程名称
# %(process)d: 打印进程ID
# %(message)s: 打印日志信息
#2.logging控制台输出
import logging

from logger_setup import setup_logger

#子logger日志器
setup_logger("first")
logger1 = logging.getLogger(__name__)

#设置默认输出日志等级
#打印DEBUG及以上日志
logging.basicConfig(level=logging.DEBUG, format = '%(asctime)s - %(pathname)s - %(levelname)s: %(message)s')

def func():
    r = input("请输入一个数字:")
    # logging.debug(type(r))
    # logging.debug(r)
    # logger.debug(type(r))
    # logger.debug(r)
    logger1.debug(type(r))
    logger1.debug(r)
    n = int(r)
    result = 100/n
    return result

print(func())
logger_setup.py

import logging

def setup_logger(filename="runtime"):
    #生成日志处理对象
    logger = logging.getLogger()    #root logger
    logger.setLevel(level=logging.DEBUG)

    #生成输出日志到文件的handler处理器
    handler = logging.FileHandler(f"{filename}.txt")  #注:FileHandler输出到文件

    #日志格式器
    formatter = logging.Formatter('%(asctime)s - %(pathname)s - %(levelname)s: %(message)s')

    #输出格式绑定到handler
    handler.setFormatter(formatter)

    #把handler绑定到logger
    logger.addHandler(handler)

    logger.info("this is info")

#2.2 logging四大组件

import logging
#生成日志处理对象
logger = logging.getLogger()
logger.setLevel(level=logging.DEBUG)

#生成输出日志到文件的handler处理器
handler = logging.FileHandler("log.txt")  #注:FileHandler输出到文件

#日志格式器
formatter = logging.Formatter('%(asctime)s - %(pathname)s - %(levelname)s: %(message)s')

#输出格式绑定到handler
handler.setFormatter(formatter)

#把handler绑定到logger
logger.addHandler(handler)

日志轮转

[root@cPen_A ~]# cd /var/log/			#注:存放日志文件
[root@cPen_A log]# cd /etc/logrotate.d/	#注:日志轮转配置文件
#注:logrotate 日志轮转
[root@cPen_A logrotate.d]# less /etc/logrotate.d/nginx 
/var/log/nginx/*log {
    create 0664 nginx root			#权限
    daily							#周期
    rotate 10						#保留10个轮转文件
    missingok						#以下 压缩操作
    notifempty
    compress
    sharedscripts
    postrotate					#注:在日志轮转后(postrotate)可以做的事情
        /bin/kill -USR1 `cat /run/nginx.pid 2>/dev/null` 2>/dev/null || true
#注:自动创建access.log,上面1条命令 重新加载nginx服务配置
    endscript
}
磁盘空间满了,但是看得见的磁盘空间(df看磁盘 和du看文件大小)远远没有达到,可能是因为服务日志文件换了(或者删除了),但是服务没有重新加载,导致这块区域一直占用,服务还在往里面写。这块区域还在使用,重新启动/加载nginx(服务),会生成新的配置文件(access.log),这块空间就真正被释放了。
[root@cPen_A nginx]# lsof |grep delete	#注:查看哪个服务占用比较多,重启了就释放了

#2.3 logging日志轮转

#logging日志轮转

import logging
import time
from logging.handlers import RotatingFileHandler
from logging.handlers import TimedRotatingFileHandler

def setup_logger(filename="runtime"):
    #生成日志处理对象
    logger = logging.getLogger()    #root logger
    logger.setLevel(level=logging.DEBUG)

    # # 生成输出日志到文件的handler处理器
    # handler = logging.FileHandler(f"{filename}.txt")  # 注:FileHandler输出到文件

    #日志轮转
    #根据大小
    # rhandler = RotatingFileHandler(f"{filename}.log",maxBytes=512, backupCount=3, encoding="utf-8")
    #maxBytes最大字节,backupCount保留文件数

    #根据时间
    #S秒
    #D天
    #M分
    #W星期
    thandler = TimedRotatingFileHandler(f"{filename}.log", when="S", interval=2, backupCount=3, encoding="utf-8")
    #注:每隔2s

    #日志格式器
    formatter = logging.Formatter('%(asctime)s - %(pathname)s - %(levelname)s: %(message)s')

    #输出格式绑定到handler
    thandler.setFormatter(formatter)

    #把handler绑定到logger
    logger.addHandler(thandler)

    for i in range(20):
        logger.info("this is info")
        time.sleep(0.5)

setup_logger()
#结果为
# runtime.log
# runtime.log.2
# runtime.log.1
# runtime.log.3
#2020-12-09 16:19:51,112 - E:/sanchuang/lianxi/logger_setup.py - INFO: this is info
# ……
#结果为
# runtime.log.2020-12-09_16-24-30
# runtime.log.2020-12-09_16-24-26
# runtime.log.2020-12-09_16-24-28
#2020-12-09 16:24:26,390 - E:/sanchuang/lianxi/logger_setup.py - INFO: this is info
# ……

#3.1 pycharm断点调试

a = 10
def func1():
    a = 20
    print(a)
func1()
a = 11
func1()

#4.1 pdb调试

import pdb
a = 1
b = a * 2
c = a + b
pdb.set_trace()		#注:打断点
d = c + 1
#结果为
# > e:\sanchuang\lianxi\31am.py(124)<module>()
# -> d = c + 1
# (Pdb)

[root@cPen python3]# python3 pdb_test.py 
> /root/python3/pdb_test.py(6)<module>()
-> d = c + 1
(Pdb) print(a)
1
(Pdb) f = c + 2
(Pdb) print(f)
5

示例:断言异常

>>> assert 1>2
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AssertionError			#注:抛出异常

示例:检查成绩必须在0-100之间

>>> score = 101
>>> assert score >= 0 and score <= 100, 'score is error'
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AssertionError: score is error

#5.1 单元测试

#func.py文件下
def add(a,b):
    return a+b

def minus(a,b):
    return a-b

def nulti(a,b):
    return a*b

def divide(a,b):
    return a/b
#单元测试
import unittest
import func

#测试用例
class TestFunc(unittest.TestCase):
    def test_add(self):
        #断言func.add(1,2)的返回  等于3
        self.assertEqual(func.add(1,2),3)

    def test_div(self):
        self.assertEqual(func.divide(2,2),1)

if __name__ == "__main__":
    #会默认执行以test开头的测试用例(都放进去)
    #main集成了这些功能,包含整个过程
    unittest.main()
#结果为
# ..
# start......
# test_add
# end......
# ----------------------------------------------------------------------
# start......
# test_div
# Ran 2 tests in 0.000s
# end......
#
# OK

if __name__ == "__main__":
    suit = unittest.TestSuite()
    suit.addTest(TestFunc("test_add"))  #添加要执行的测试用例
    runner = unittest.TextTestRunner()   #执行测试用例
    runner.run(suit)
#结果为
# .
# start......
# test_add
# end......
# ----------------------------------------------------------------------
# Ran
# 1
# test in 0.000
# s
#
# OK

#unittest包含了四个模块:
#TestCase
#TestSuite
#TextTestRunner
#TestLoader  :将Testcase 加载到TestSuite
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

mycpen

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值