Python logging模块实现同时向控制台和文件打印日志
原创
文章标签 python 开发语言 后端 日志文件 日志输出 文章分类 Python 后端开发
©著作权归作者所有:来自51CTO博客作者CorwinPC的原创作品,请联系作者获取转载授权,否则将追究法律责任
有时候我们在运行程序的时候,希望日志既要在控制台面板输出,同时也要在日志文件中写入,这样有利于我们实时掌握程序的运行状态,也方便程序出错的时候,能够在日志文件中分析程序中存在的错误。
#!/usr/bin/python# -*- coding: UTF-8 -*-"""@author: Roc-xb"""import logging, sysdef config_logging(file_name: str, console_level: int = logging.INFO, file_level: int = logging.DEBUG): file_handler = logging.FileHandler(file_name, mode='a', encoding="utf8") file_handler.setFormatter(logging.Formatter( '[%(asctime)s %(levelname)s] %(message)s', datefmt="%Y-%m-%d %H:%M:%S" )) file_handler.setLevel(file_level) console_handler = logging.StreamHandler(sys.stdout) console_handler.setFormatter(logging.Formatter( '[%(asctime)s %(levelname)s] %(message)s', datefmt="%Y-%m-%d %H:%M:%S" )) console_handler.setLevel(console_level) logging.basicConfig(level=min(console_level, file_level), handlers=[file_handler, console_handler])if __name__ == '__main__': # 参数解释: # 第一个参数:日志文件名称 # 第二个参数:控制台日志输出最小等级(默认:logging.INFO) # 第三个参数:文件日志输出最小等级(默认:logging.DEBUG) config_logging("test.log", logging.INFO, logging.DEBUG) logger = logging.getLogger(__name__) logger.info("一般日志") logger.warning("警告日志") logger.error("错误日志")
- 赞
- 收藏
- 评论
- *举报
下一篇:python写入Excel时,将路径或链接以超链接的方式写入
Original: https://blog.51cto.com/YangPC/5483037
Author: CorwinPC
Title: Python logging模块实现同时向控制台和文件打印日志
相关阅读1
Title: 03_Django-GET请求和POST请求-设计模式及模板层
03_Django-GET请求和POST请求-设计模式及模板层
视频🔗:https://www.bilibili.com/video/BV1vK4y1o7jH
博客🔗:https://blog.csdn.net/cpen_web
一. GET请求和POST请求
定义
·无论是GET还是POST,统一都由
视图函数
接收请求,通过判断request.method区分具体的请求动作
·样例:
if requests.method == 'GET':
处理GET请求时的业务逻辑
elif requests.method == 'POST':
处理POST请求的业务逻辑
else:
其他请求业务逻辑
GET请求方式中,如果有数据需要传递给服务器,通常会用 查询字符串(Query String)
传递【注意: 不要传递敏感数据
】
URL格式:xxx ?参数名1=值1&参数名2=值2...
- 如:http://127.0.0.1:8000/page1 ?a=100&b=200
服务器端接收参数
获取客户端请求GET请求提交的数据
·方法示例:
request.GET['参数名'] # QueryDict
request.GET.get('参数名', '默认值')
request.GET.getlist('参数名')
# mypage?a=100&b=200&c=300&b=400
# request.GET=QueryDict({'a': ['100'], 'b': ['200', '400'], 'c': ['300']})
# a = request.GET['a']
# b = request.GET['b'] # Error
·思考:之前的计算器功能,能否拿查询字符串做?
http://127.0.0.1:8000/整数/操作符/整数
http://127.0.0.1:8000/cal?x=10&y=20&op=add
POST处理
·POST请求动作,一般用于
向服务器提交大量/隐私数据
·客户端通过表单等POST请求将数据传递给服务器端,如:
·服务器端接收参数
通过request.method来判断是否为POST请求,如:
if request.method == 'POST':
处理POST请求的数据并响应
else:
处理非POST请求的响应
取消csrf验证
- 禁止掉settings.py中MIDDLEWARE中的CsrfviewsMiddleWare的中间件
MIDDLEWARE = [
...
# 'django.middleware.csrf.CsrfViewMiddleware',
...
]
小节
·Django处理GET请求
查询字符串 - 少量数据传递
·Django处理POST请求
专用于浏览器提交数据
二. Django的设计模式及模板层
MVC和MTV
传统的MVC
MVC代表
Model-View-Controller
(模型-视图-控制器)模式。
M模型层(Model)
,主要用于对数据库层的封装V视图层(View)
,用于向用户展示结果(WHAT + HOW)C控制(Controller)
,用于处理请求、获取数据、返回结果(重要)
作用: 降低模块间的耦合度(解耦)
Django的MTV模式
MTV代表
Model-Template-View
(模型-模板-视图)模式。
M模型层(Model)
负责与数据库交互T模板层(Template)
负责呈现内容到浏览器(HOW)V视图层(View)
是核心,负责接收请求、获取数据、返回结果(WHAT)
作用: 降低模块间的耦合度(解耦)
演示
/settings.py
TEMPLATES = [
{
...
'DIRS': [os.path.join(BASE_DIR, 'templates')],
...
模板的加载方式
方案1 - 通过loader获取模板,通过HttpResponse进行响应(特点:麻烦)
在视图函数中:
from django.template import loader
# 1.通过 loader 加载模板
t = loader.get_template("模板文件名")
# 2.将 t 转换成 HTML 字符串
html = t.reader(字典数据)
# 3.用响应对象将转换的字符串内容返回给浏览器
return HttpResponse(html)
方案2 - 通过render() 直接加载并响应模板(特点:方便,大量使用这种)
在视图函数中:
from django.shortcuts import render
return render(request, '模板文件名', 字典数据)
演示
http://127.0.0.1:8000/test_html
/urls.py
urlpatterns = [
...
path('test_html', views.test_html)
]
/views.py
def test_html(request):
from django.shortcuts import render
dic = {'username': 'peng', 'age': 23}
return render(request, 'test_html.html', dic)
/templates/test_html.html
{{ username }}是模板层的~~~~
Original: https://www.cnblogs.com/mycpen/p/15898758.html
Author: mycpen
Title: 03_Django-GET请求和POST请求-设计模式及模板层
相关阅读2
Title: 设计模式(Python语言)----工厂方法模式
推荐文章
2023年,摸鱼计划系列活动又跟大家见面了,我们活动规则不变,福利升级! 新的一年,继续把工作学习中的bug处理、碎片知识,统统记录到博客里。留下自己在技术之路的成长足迹。
推荐原创51CTO博客13天前10000+阅读11点赞733评论1收藏
在51CTO博客成功发布第一篇博文,可领取新人福利,奖品三选一。来分享属于自己的技术踩坑经验吧!
推荐原创51CTO博客95天前10000+阅读16点赞11评论5收藏
出现网关不亮灯的原因就是配置问题,仔细检查网关和微端程序的IP地址有没有填错,如有填错更改过来即可。微端无连接不更新的问题解决方法1、端口不对微端没有更新,玩家进入游戏是地图跟装备都看不见,是漆黑的,微端显示连接失败,好吧,那么从头开始检查,检查什么地方呢,第一检查微端网关程序,看看上面是否全部显示连接成功了,如果是成功的,那么看一下列表里面的端口对不对的上服务器IP都是连接成功的,没有连
原创会开服的小杰2小时前147阅读1点赞评论收藏
本文首发自「慕课网」,想了解更多IT干货内容,程序员圈内热闻,欢迎关注!作者|慕课网精英讲师 然冬基于 IEEE 754 标准的双精度 64 位二进制格式的值(-(253 -1) 到 253 -1)。——MDN在 JavaScript 只有浮点数(可以理解成带有小数点的数)。数字就是我们日常使用的数字,在 JavaScript 中默认是十进制的。10;-1;1.1;10.0;+0;-0;99999
原创imooc慕课君2小时前154阅读点赞评论收藏
本篇介绍下flea-jersey模块的文件下载功能
原创Huazie2小时前143阅读点赞评论收藏
_app.js只加入一个 ThemeProvide 具体在 ThemeProvide 中import type { AppProps } from "next/app
原创JediHongbin2小时前146阅读点赞评论收藏
概念数据库连接池其实就是一个容器(集合),存放数据库连接的容器。当系统初始化好后,容器被创建,容器中会申请一些连接对象,当用户来访问数据库时,从容器中获取连接对象,用户访问完之后,会将连接对象归还给容器。好处1.节约资源2.用户访问高效实现标准接口:DataSource javax.sql包下的方法:获取连接:getConnection()归还连接:Connection.close()。如果连接对
原创共饮一杯无2小时前138阅读1点赞评论1收藏
项目中需要自定义icon,在项目中通用html使用css样式.icon-save { /使用自己的图片来替换/ background: url('图片地址') center no-repeat; background-size: contain;}.icon-save::before { /*before
原创不叫猫先生3小时前138阅读点赞评论收藏
二叉树的锯齿形层序遍历(树、广度优先搜索)给定一个二叉树,返回其节点值的锯齿形层序遍历。(即先从左往右,再从右往左进行下一层遍历,以此类推,层与层之间交替进行)。例如:给定二叉树3,9,20,null,null,15,7,3/\920/\157返回锯齿形层序遍历如下:3,20,9,15,7解答:javapublicclassTreeNode{intval;TreeNodeleft;TreeNode
原创共饮一杯无3小时前141阅读1点赞评论1收藏
1.情景展示 where限制条件后面如果想要加select语句的话,如何实现? 2.原因分析 通常情况下,where后面跟的是:clo
原创Marydon3小时前150阅读点赞评论收藏
编码进化回忆上次内容上次 研究了 视频终端的 演化 从VT05 到 VT100从 黑底绿字 到 RGB 24位真彩色形成了 VT100选项从而 将颜色 数字化 了生活中我们更常用 10个数字 但是 计算机中 用二进制日常计数的十进制数 是如何存储进计算机的呢??从10进制到2进制日常生活中 为什么用10进制? 是因为 人的生理结构计算机中 使用2进制 是因为 计算机的生理结构 电灯、开关
原创overmind19803小时前134阅读点赞评论收藏
程序员的日历,真的不用上网查,直接一条命令就可以默认显示本月的日历(20230214)bashcal二月2023日一二三四五六12345678910111213141516171819202122232425262728显示指定年份的日历bashcaly20232023一月二月三月日一二三四五六日一二三四五六日一二三四五六12345671234123489101112131456789101156
原创彭世瑜3小时前140阅读点赞评论收藏
效果如下图所示:我们实际上使用了2D来模拟3D效果。!(https://s2.51cto.com/images/blog/202302/14095121_63eae919a42774018.png?xossprocess=image/watermark,size_14,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_20
原创JerryWang汪子熙3小时前148阅读点赞评论收藏
写在前面+K9s是一个基于终端UI的K8S管理工具+博文内容为k9s在windows、Linux以及docker安装Demo+简单的热键使用。+理解不足小伙伴帮忙指正
原创山河已无恙3小时前136阅读点赞评论收藏
写在前面+kubebox是一个轻量的k8s管理工具,可以基于命令行终端或Web端+博文内容涉及:kubebox不同方式的安装下载,简单使用。+如果希望轻量一点,个人很推荐这个工具,轻量,而且使用简单。+理解不足小伙伴帮忙指正我所渴求的,無非是將心中脫穎語出的本性付諸生活,為何竟如此艱難呢赫尔曼·黑塞《德米安》简单介绍Kubebox是一个类似k9s的基于命令行终端的k8s管理工具,可以直接下载可执行
原创山河已无恙3小时前143阅读点赞评论收藏
本文将给大家分享Java并发编程相关的知识点,具体将对Java常见的并发编程方式和手段进行总结,以便可以从使用角度更好地感知Java并发编程带来的效果。
原创京东云开发者3小时前146阅读点赞评论收藏
软件开发入门教程网Bootstrap4 面包屑导航(Breadcrumb)面包屑导航是一种基于网站层次信息的显示方式。以博客为例,面包屑导航可以显示发布日期、类别或标签。它们表示当前页面在导航层次结构内的位置,是在用户界面中的一种导航辅助。Bootstrap 中的面包屑导航是一个简单的带有 .breadcrumb class 的无序列表。分隔符会通过 CSS(bootstrap
原创雪奈椰子3小时前136阅读点赞评论收藏
一、前言 - webpack热更新Hot Module Replacement,简称HMR,无需完全刷新整个页面的同时,更新模块。HMR的好处,在日常开发工作中体会颇深:节省宝贵的开发时间、提升开发体验。刷新我们一般分为两种:一种是页面刷新,不保留页面状态,就是简单粗暴,直接window.location.reload()。另一种是基于WDS (Webpack-
原创Seattle小小瓜3小时前136阅读点赞评论收藏
1.背景Spring的核心思想就是容器,当容器refresh的时候,外部看上去风平浪静,其实内部则是一片惊涛骇浪,汪洋一片。Springboot更是封装了Spring,遵循约定大于配置,加上自动装配的机制。很多时候我们只要引用了一个依赖,几乎是零配置就能完成一个功能的装配。我非常喜欢这种自动装配的机制,所以在自己开发中间件和公共依赖工具的时候也会用到这个特性。让使用者以最小的代价接入。想要把自动装
原创Seattle小小瓜3小时前135阅读点赞评论收藏
一. pyinstaller和Nuitka使用感受1.1 使用需求这次也是由于项目需要,要将python的代码转成exe的程序,在找了许久后,发现了2个都能对python项目打包的工具——pyintaller和nuitka。这2个工具同时都能满足项目的需要:隐藏源码。这里的pyinstaller是通过设置key来对源码进行加密的;而nuitka则是将python源码转成C++(这里得到的是二进制的
原创LinkSLA3小时前146阅读点赞评论收藏
本文主要讲述了Android客户端模块化开发的痛点及解决方案,详细讲解了方案的实现思路和具体实现方法。
原创vivo互联网3小时前136阅读点赞评论收藏
Original: https://blog.51cto.com/u_11160105/5514986
Author: redrose2100
Title: 设计模式(Python语言)----工厂方法模式
相关阅读3
Title: Python 快速排序法(转)
方法解读:
例:对初始序列:"6 1 2 7 9 3 4 5 10 8"采用快速排序法:
一、分别从初始序列"6 1 2 7 9 3 4 5 10 8"两端开始"探测"。
先 从右往左找一个 小于6的数,再从 左往右找一个大于 6的数,然后 交换他们。
这里可以用两个变量 i 和 j ,分别指向序列最左边和最右边。
我们为这两个变量起个好听的名字" 哨兵i"和" 哨兵j"。
刚开始的时候让 哨兵i指向序列的最左边(即 i=1),指向 数字6。
让 哨兵j指向序列的最右边(即 j=10),指向 数字8。
二、首先哨兵j 开始出动。
因为此处设置的基准数是最左边的数,所以需要让 哨兵j先出动,这一点非常重要(请自己想一想为什么)。
哨兵j一步一步地向左挪动(即 j--),直到找到一个小于6的数停下来。
接下来 哨兵i 再一步一步向右挪动(即 i++),直到找到一个数大于6的数停下来。
最后 哨兵j 停在了数字5面前, 哨兵i 停在了数字7面前。
现在交换 哨兵i 和 哨兵j 所指向的元素的值。
到此,第一次交换结束。
三、接下来开始 哨兵j 继续向左挪动(再友情提醒,每次必须是 哨兵j先出发)。
他发现了4(比基准数6要小,满足要求)之后停了下来。
哨兵i 也继续向右挪动的,他发现了9(比基准数6要大,满足要求)之后停了下来。
此时再次进行交换。
四、第二次交换结束,"探测"继续。
哨兵j继续向左挪动,他发现了3(比基准数6要小,满足要求)之后又停了下来。
哨兵i 继续向右移动,糟啦!此时 哨兵i 和 哨兵j 相遇了, 哨兵i 和 哨兵j 都走到3面前。
说明此时"探测"结束。
我们将基准数6和3进行交换。交换之后的序列如下。
五、 到此第一轮"探测"真正结束。
此时以基准数6为分界点,6左边的数都小于等于6,6右边的数都大于等于6。
回顾一下刚才的过程,其实 哨兵j 的使命就是要找小于基准数的数,而 哨兵i 的使命就是要找大于基准数的数,直到 i 和 j 碰头为止。
现在基准数6已经归位,它正好处在序列的第6位。
此时我们已经将原来的序列,以6为分界点拆分成了两个序列,左边的序列是"3 1 2 5 4",右边的序列是"9 7 10 8"。
接下来还需要分别处理这两个序列。因为6左边和右边的序列目前都还是很混乱的。
不过不要紧,我们已经掌握了方法,接下来只要模拟刚才的方法分别处理6左边和右边的序列即可。
六、现在先来处理6左边的序列现吧。
左边的序列是"3 1 2 5 4"。请将这个序列以3为基准数进行调整,使得3左边的数都小于等于3,3右边的数都大于等于3。好了开始动笔吧。
如果你模拟的没有错,调整完毕之后的序列的顺序应该是。
2 1 3 5 4
OK,现在3已经归位。
接下来需要处理3左边的序列"2 1"和右边的序列"5 4"。
对序列"2 1"以2为基准数进行调整,处理完毕之后的序列为"1 2",到此2已经归位。
序列"1"只有一个数,也不需要进行任何处理。至此我们对序列"2 1"已全部处理完毕,得到序列是"1 2"。
序列"5 4"的处理也仿照此方法,最后得到的序列如下。
1 2 3 4 5 6 9 7 10 8
七、对于序列"9 7 10 8"也模拟刚才的过程,直到不可拆分出新的子序列为止。
最终将会得到这样的序列,如下。
1 2 3 4 5 6 7 8 9 10
八、到此,排序完全结束。
细心的同学可能已经发现,快速排序的每一轮处理其实就是将这一轮的基准数归位,直到所有的数都归位为止,排序就结束了。
下面上个霸气的图来描述下整个算法的处理过程。
九、原始网址:https://blog.csdn.net/adusts/article/details/80882649
十、Python程序:
#快速排序法一:有小到大排序
def quickSort(arr,left,right):#arr:待排序的数列;left:数列开始的下标索引;right:数列结束的下标索引
if left > right:#如果开始索引大于结束索引
return
temp=arr[left];#取最左边的数为 基准数
i,j=left,right
while i!= j:#现从右边开始找
while arr[j]>=temp and i
将 基准数 归位
arr[left]=arr[i]
arr[i]=temp
quickSort(arr,left,i-1)#递归:继续处理左边的
quickSort(arr,i+1,right)#递归:继续处理右边的
测试
arr=[10,7,8,8,9,1,5]
n=len(arr)
quickSort(arr,0,n-1)
print("排序后的数组:")
for i in range(n):
print("%d" %arr[i])
#快速排序法二:由大到小排序
def quickSort(arr,left,right):#arr:待排序的数列;left:数列开始的下标索引;right:数列结束的下标索引
if left > right:#如果开始索引大于结束索引
return
temp=arr[left];#取最左边的数为 基准数
i,j=left,right
while i!= j:#现从右边开始找
while arr[j] and i
将 基准数 归位
arr[left]=arr[i]
arr[i]=temp
quickSort(arr,left,i-1)#递归:继续处理左边的
quickSort(arr,i+1,right)#递归:继续处理右边的
测试
arr=[10,7,8,8,9,1,5]
n=len(arr)
quickSort(arr,0,n-1)
print("排序后的数组:")
for i in range(n):
print("%d" %arr[i])
Original: https://www.cnblogs.com/xiangers/p/15433774.html
Author: xiangers
Title: Python 快速排序法(转)