范文健康探索娱乐情感热点
投稿投诉
热点动态
科技财经
情感日志
励志美文
娱乐时尚
游戏搞笑
探索旅游
历史星座
健康养生
美丽育儿
范文作文
教案论文

logging多线程调试时用来代替print和单步调试

  当你要写多线程项目时,不免要调试错误,要debug。
  一般debug的工具就是打印函数print, 调试工具gdb进行单步调试,但是多线程时,单步调试就很鸡肋了,这时就需要打印日志了
  没错,打印日志无疑是调试多线程工程的高效工具了。
  在python中开发,就要用到logging日志库了
  logging库已经封装好日志需要的基本功能,能够实现在文件里,在命令行等写日志
  还能输出日志信息的类型,如debug,warning,error等
  细节在这里有所介绍:
  https://docs.python.org/3/howto/logging.html
  文本介绍一下,第一次使用logging时,要熟悉logging时,需要用一个非常简单的例子一个简单的例子
  先看一个最简单的例子:import logging logging.warning("Watch out!")  # will print a message to the console logging.info("I told you so")  # will not print anything
  运行以上代码:WARNING:root:Watch out!
  printed out on the console. The INFO  message doesn’t appear because the default level is WARNING . The printed message includes the indication of the level and the description of the event provided in the logging call, i.e. ‘Watch out!’. Don’t worry about the ‘root’ part for now: it will be explained later. The actual output can be formatted quite flexibly if you need that; formatting options will also be explained later.把日志写进文件里
  import logging logging.basicConfig(filename="example.log", encoding="utf-8", level=logging.DEBUG) logging.debug("This message should go to the log file") logging.info("So should this") logging.warning("And this, too") logging.error("And non-ASCII stuff, too, like Øresund and Malmö")
  输出结果为:DEBUG:root:This message should go to the log file INFO:root:So should this WARNING:root:And this, too ERROR:root:And non-ASCII stuff, too, like Øresund and Malmö
  如果你想每次都在一个新的日志文件中写日志,那么使用filemode="w"参数:logging.basicConfig(filename="example.log", filemode="w", level=logging.DEBUG)
  从不同的模块里写同一个日志
  分别在main 函数里,在mylib.py里写日志# myapp.py import logging import mylib  def main():     logging.basicConfig(filename="myapp.log", level=logging.INFO)     logging.info("Started")     mylib.do_something()     logging.info("Finished")  if __name__ == "__main__":     main() # mylib.py import logging  def do_something():     logging.info("Doing something")
  运行后的输出:INFO:root:Started INFO:root:Doing something INFO:root:Finished
  把变量写进日志里
  import logging logging.warning("%s before you %s", "Look", "leap!")
  以上代码会显示:WARNING:root:Look before you leap!
  改变数据显示的格式
  该 format参数的值import logging logging.basicConfig(format="%(levelname)s:%(message)s", level=logging.DEBUG) logging.debug("This message should appear on the console") logging.info("So should this") logging.warning("And this, too")
  以上代码会显示:DEBUG:This message should appear on the console INFO:So should this WARNING:And this, too
  显示时间戳
  还是该format:import logging logging.basicConfig(format="%(asctime)s %(message)s") logging.warning("is when this event was logged.")
  以上代码会输出2010-12-12 11:41:42,612 is when this event was logged.
  如果想自己设定时间的格式:import logging logging.basicConfig(format="%(asctime)s %(message)s", datefmt="%m/%d/%Y %I:%M:%S %p") logging.warning("is when this event was logged.")
  会这样显示:12/12/2010 11:46:36 AM is when this event was logged.
  基础使用方法看完了,推荐掌握更高级的 logger的用法
  logging库中用了模块化的思路,把日志的整体功能用了4个基本的模块来完成:
  Loggers,Handlers,Filters,Formatters
  其中,Handlers,主要配置将信息写到命令行,还是写到文件里。
  Filters,是对信息本身的过滤,决定那些信息不写,那些信息写。
  Formatters决定信息输出的格式。比如是否输出时间,是否输出logger本身的名字等,决定那些信息在前,那些信息在后等。
  Logger就是Handler,Filter,Formatter配置的一个日志对象了。
  下面我们逐个说一下这4个类:Loggers
  它有三个功能,1 提供分级日志的输出,比如 WARNING,ERROR,INFO等不同等级。2. 它可以决定哪些信息输出,哪些信息不输出。3 它可以将一条信息发给命令行和文件,可以把一条信息发给多个handler去处理。
  logger 最常用的成员方法大概分两类:配置和信息发送
  以下是常用的配置函数:
  Logger.setLevel() 设定信息记录的等级。如果一条信息的等级比我们设定的低,那么就不对此条信息进行处理。信息一共分为:DEBUG,INFO,WARNING,ERROR,CRITICAL 五个级别,其中DEBUG是最低的等级,CRITICAL是最高的等级。
  Logger.addHandler() 和 Logger.removeHandler(),添加或者删除信息处理器Handler。这个信息处理器就是定义了将日志写入命令行,还是写入文件,或者写入邮件等。
  Logger.addFilter() 和 Logger.removeFilter() .添加或者删除信息过滤器Filter。这个信息过滤器,决定了哪些信息不显示。
  可以看到,信息过滤器,信息处理器,信息等级共同配置了logger.
  并不是每个logger你都需要去配置一遍,你可以利用logger的继承机制,只配置父logger.
  一旦配置好logger之后,就可以用以下函数来在你自己代码的任意位置来记录日志了。
  Logger.debug(),Logger.info(),Logger.warning(),Logger.error()和Logger.critical.这些函数的功能都是建立了日志记录信息,不同的是,函数名字就代表了其建立的日志信息的等级。
  Logger.exeception()建立一个与Logger.error()比较相似的信息。但是Logger.exception()是放入一个追踪盏里面的。所以,只有在exception handler处理器中,才能使用它。
  Logger.log()发送一个LOG 等级的信息,使用LOG等级的信息稍微繁琐些,因为使用LOG等级可以自定义等级。
  getLogger() 返回一个logger的引用,如果指定了名字,那么返回特定名字对应的logger,如果没有指定名字,那就返回一个名字为root的loger的引用名字root,或者你指定的名字是一种级连结构。用同样的名字去调用getLogger(),会得到同样的值。logger的名字也决定了logger在树结构中的层级。例如:这里有一个logger的名字为foo,那么foo.bar,foo.bar.baz,还有foo.bam都是foo的子孙,logger还有一个有效等级level的概念。这个有效等级其实就是决定debug,info,warning等不同类型的消息是否进行记录。因为logger本身有了父子那样的继承关系,所以有效等级level也是可以继承的。如果子logger没有设定了自身的level,那么就把父logger的level继承过来使用。如果子logger本身设定了level,就用自身这个level.如果父logger仍然没有设定level,那就看父logger的父logger,一直这么追述下去,就会追述到root上,所以,我们必须给root设定一个level,或者默认一个level,方便root的子logger去继承。我们给root设定的默认levle为WARNING.如果有些日志的level,相比我们设定的WARNING低,那么它就不会被传递给Handler去处理,就不会被打印出来,或者记录进日志文件。另外logger的属性也是可继承的,所以就只配置一下root logger即可,没有root logger时,只用配置一个相对的那个根logger就行了
  Handlers信息处理器
  handler 信息处理器是负责信息分发给不同的目的地的,这个目的地可能是命令行,也可能是文件,或者邮件。分发时,同样要检查信息本身的等级severity.一个logger可以用addHandler()函数添加0个或者多个handlers。比如有这样一个场景,希望发送所有的log等级的信息到一个log文件内。所有的等级为错误的信息到stdout 标准输出上,发送所有的critical信息到邮件上。这样的场景需要3个不同的处理器,每个处理器负责发送相应等级的信息到相应的目的地。
  标准库里包含一些处理器类型,本教程主要使用StreamHandler 和 FileHandler两种信息处理器。
  处理器中的成员函数非常少,我们用来配置处理器的成员函数大概有这个几个:
  setLevel(),用来设置处理器处理的信息等级。注意到logger中有setLevel(),而处理器中也有setLevel(),也就是说,logger把信息通过信息等级过滤一遍后,logger内的处理器需要根据处理器自身的功能设定,再根据信息等级来过滤一遍。
  setFormatter() 为处理器设定一种信心记录的格式Formatter
  addFilter() removeFilter()函数添加信息过滤器或者删除信息过滤器的函数。
  到这里,我们发现,logger类中,将信息发送到不同的目的地就依赖Handlers实现的,
  所有Handler就需要用Formatter和Filter来配置一下。接下来,我们看看Formatter和Filter.Formatters
  它决定了信息显示的顺序,结构和内容。可以直接操作formatter的相关类,也可以自己继承 formatter类,去完成自己的设定。formatter的构造函数需要3个可选的参数:字符串格式的信息,日期,一个符号。
  logging.Formatter.__init__(fmt=None,datafmt=None,style="%")
  如果这里没有设定参数,就使用默认参数。对于fmt来说,就显示原来信息,对于datafmt来说,就以年-月-日 时:分:秒的合适显示。
  下面的fmt就定义了一个按照 时间-信息等级-信息本身 来记录日志的方法:"%(asctime)s - %(levelname)s - %(message)s"
  如何将信息处理器,以及信息处理器的Formatters和过滤器配置给Logger?
  这里有三种方法:写代码,调用相关的成员函数来完成配置。写一个配置文件,用 fileConfig () 函数来完成配置。写一个字典,用dictConfig()函数来完成配置。
  写代码配置logging的例子:import logging  # create logger logger = logging.getLogger("simple_example") logger.setLevel(logging.DEBUG)  # create console handler and set level to debug ch = logging.StreamHandler() ch.setLevel(logging.DEBUG)  # create formatter formatter = logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s")  # add formatter to ch ch.setFormatter(formatter)  # add ch to logger logger.addHandler(ch)  # "application" code logger.debug("debug message") logger.info("info message") logger.warning("warn message") logger.error("error message") logger.critical("critical message")
  运行结果为:$ python simple_logging_module.py 2005-03-19 15:10:26,618 - simple_example - DEBUG - debug message 2005-03-19 15:10:26,620 - simple_example - INFO - info message 2005-03-19 15:10:26,695 - simple_example - WARNING - warn message 2005-03-19 15:10:26,697 - simple_example - ERROR - error message 2005-03-19 15:10:26,773 - simple_example - CRITICAL - critical message
  写配置文件配置logging的例子:import logging import logging.config  logging.config.fileConfig("logging.conf")  # create logger logger = logging.getLogger("simpleExample")  # "application" code logger.debug("debug message") logger.info("info message") logger.warning("warn message") logger.error("error message") logger.critical("critical message")
  代码中所需要的配置文件ogging.conf的具体内容为 :[loggers] keys=root,simpleExample  [handlers] keys=consoleHandler  [formatters] keys=simpleFormatter  [logger_root] level=DEBUG handlers=consoleHandler  [logger_simpleExample] level=DEBUG handlers=consoleHandler qualname=simpleExample propagate=0  [handler_consoleHandler] class=StreamHandler level=DEBUG formatter=simpleFormatter args=(sys.stdout,)  [formatter_simpleFormatter] format=%(asctime)s - %(name)s - %(levelname)s - %(message)s
  以上代码的输出为:$ python simple_logging_config.py 2005-03-19 15:38:55,977 - simpleExample - DEBUG - debug message 2005-03-19 15:38:55,979 - simpleExample - INFO - info message 2005-03-19 15:38:56,054 - simpleExample - WARNING - warn message 2005-03-19 15:38:56,055 - simpleExample - ERROR - error message 2005-03-19 15:38:56,130 - simpleExample - CRITICAL - critical message
  显然,配置文件修改起来相对容易很多。
  还有更方便的配置方式,使用字典来配置:logging_conf_dict={ version: 1 formatters:   simple:     format: "%(asctime)s - %(name)s - %(levelname)s - %(message)s" handlers:   console:     class: logging.StreamHandler     level: DEBUG     formatter: simple     stream: ext://sys.stdout loggers:   simpleExample:     level: DEBUG     handlers: [console]     propagate: no root:   level: DEBUG   handlers: [console] }   import logging import logging.config  logging.config.fileConfig("logging_conf.dict")  # create logger logger = logging.getLogger("simpleExample")  # "application" code logger.debug("debug message") logger.info("info message") logger.warning("warn message") logger.error("error message") logger.critical("critical message")
  运行结果与上面一样。
  到这里,基本完成了logging库的比较常用的使用方式。其实后面还有一些琐碎的信息:
  比如在什么情况下,需要使用一个什么都不做的处理器NullHandler(),
  还有关于信息等级的更详细的解释:
  Level
  Numeric value
  CRITICAL
  50
  ERROR   40
  WARNING   30
  INFO   20
  DEBUG   10
  NOTSET   0
  以及如何自定义信息等级。   还有关于异常的处理   还有关于信息的,信息都是字符串的。不过你也可以直接把某个类作为信息抛出来,因为类会自动调用其__str__()函数,返回一个类的字符串回来。   还有就是优化性能的一些小技巧if logger.isEnabledFor(logging.DEBUG): logger.debug("Message with %s, %s", expensive_func1(), expensive_func2())   这里就编写expensive_func1 和 expensive_func2 来完成设定数据格式。   以下表格也显示了如何收集运行log的代码文件信息,线程信息,进程信息,处理器信息   以及如何操作才能收集代码文件信息,线程信息,进程信息,以及处理器信息。   What you don’t want to collect   How to avoid collecting it   Information about where calls were made from.   Set logging._srcfile to None . This avoids calling sys._getframe(), which may help to speed up your code in environments like PyPy (which can’t speed up code that usessys._getframe()).   Threading information.   Set logging.logThreads to False .   Current process ID (os.getpid())   Set logging.logProcesses to False .   Current process name when using multiprocessing to manage multiple processes.   Set logging.logMultiprocessing to False .   我们一般会使用收集代码文件,线程,进程等信息,因为这样大大方便了多线程多进程工程的调试。

在中国市场陷入苦战,三星电子急了,成立中国事业革新组木叶日语专注于日本社会日本文化的介绍以及日语学习的专业头条号,带你认识一个真实的日本。三星电子为了打开陷入苦战的中国事业的突破口,最近新设了中国事业革新组。这是为了打破在OPPOV达尼KATCHG22021年最打动人心的数字家庭产品视频加载中在便携蓝牙音箱市场里,可供消费者选择的产品不可谓不丰富,特别是在传统音箱大牌加入后,便携蓝牙音箱听个响的尴尬及低端局面早已成为过去时,设计和音质成为了消费者关注的重点。作碰瓷还吐槽一加Nord2?小米POCOF3GT称比Nord2提供更多碰瓷还吐槽一加Nord2?小米POCOF3GT称比Nord2提供更多!一加Nord作为一加旗下定位中端的品牌,自去年开始推出首款一加Nord后,日前已经官宣将于7月22日在印度推出半入耳低延迟好降噪,华为FreeBuds4降噪耳机陪你私享欧洲杯对于足球爱好者来说,最近火热的欧洲杯,尤其是7月12日凌晨的决赛肯定不容错过。不过凌晨爬起来看球赛,不仅要追求沉浸感,还得防止打扰到家人和邻居,可以说是非常的辛苦。而作为一个真无线小米折叠屏设计图?网传小米折叠屏设计?根据图片可知小米采用上下对折式方式,与三星折叠屏类似根据图片得知采用前置双挖孔设计,搭载tepec接口,可能会采用100w快充,依旧延续11u的副屏虽然和三星某号外!个人信息安全刻不容缓,OPPO靠这几招为用户保驾护航相信资深影迷一定记得新一代港片黄金三角刘青云古天乐以及成龙劝他投降的阿祖合拍的窃听风云系列电影,里面讲述的更多是金融行业的尔虞我诈以及各种高科技窃听手法,不过今天我并不是来给大家科华为平板的成功带动安卓手机厂商的平板热?也许吧今年平板市场很热闹,当然安卓平板也很热闹,但是华为应该算退出安卓平板市场了,毕竟现在是鸿蒙系统,但是安卓平板最近看起来的成功,也许就是因为华为的努力?有点是这样吧!至少在国内市场,除P50系列外,7月29日发布会还有儿童手表和华为手环6ProIT之家7月9日消息此前有消息称华为P50系列将于7月29日发布。数码博主长安数码君今日表示,华为7月29日的发布会上还将推出一款儿童手表和华为手环6Pro,原定于同期发布的华为V国产品牌已经崛起,苹果不再是第一首选,vivo成功夺冠相信大家能明显感受到,自从华为芯片被断供之后,华为手机市场份额猛降,各大手机厂商都想争夺华为手机市场,各大手机厂商都在纷纷发力,谁将会是华为的接班人呢?答案揭晓了,前不久,全球知名推荐3款主打拍照的手机日常拍照少不了,旅行更是必备哈喽,大家好!欢迎您点开笑呵呵的小丑的文章,您的每一次浏览都是对小编最大的鼓励!事不宜迟,咱们进入本篇的正题。现在的手机有主打性能的,有主打拍照的,还有主打颜值的,这些都是手机的不华为P60Pro搭载麒麟1020芯片2亿像素主镜头四曲无孔屏设计大家好,又见面了,我是专注二手手机拍卖的优品拍拍虽然现在华为P50系列还未发布,然而现在鸿蒙系统已正式投入使用,芯片的研发并未放弃。海思还在研发3纳米工艺芯片,将来台积电在无法代工
独家腾讯两大事业群同时调整副总裁,涉及腾讯教育信息平台与服务线记者崔鹏编辑文姝琪12月1日,界面新闻独家获悉,腾讯PCG和CSIG两大事业群将同时启动内部调整现任腾讯公司副总裁殷宇(Mel)将调任云与智慧产业事业群(CSIG)智慧教育行业负责新鲜早科技丨爱奇艺被曝大裁员数字支付巨头Square将更名为Block瑞幸咖啡4。6亿美元债券重组计划获债权人批准21世纪经济报道记者杨清清实习生史贝琪综合报道早上好,新的一天又开始了。在过去的24小时内,科技行业发生了哪些有意思的事情?来跟21tech一起看看吧。巨头风向标1爱奇艺被曝大裁员小红花也有大用处日拱一卒筑牢共享出行基石随着冬季的到来,顺风车等交通运输新业态的重要性进一步凸显。与巡游出租车相比,顺风车解决了通勤高峰期打不到车的问题与专车网约车相比,它又解决了费用贵的问题。不过,就像一枚硬币的两面,你买思皓新能源车到底图什么图它续航短?图它充电慢?答案当然不是的。买车看自己开心咯,任何一个厂家都不可能做到令每个人都满意,前两天朋友告诉我一句话,真是让人醍醐灌顶。她说生活就应该删繁就简,自己算自己的账本一天一个编程小知识之Java中的函数式编程函数式编程的一个特点就是,允许把函数本身作为参数传入另一个函数,还允许返回一个函数。为什么java中可以使用函数式编程Java本身是面向对象的程序设计语言,要想在Java中使用函数美国公司注册亚马逊店铺要注意哪些问题?前两天碰到这样一个问题,有一个卖家,有美国公司资料,想要找我们代理注册亚马逊店铺,因为注册费用的问题,一直在纠结。代注册亚马逊店铺是不是在割韭菜?这是很多新卖家心里的一个疑问。扫地以数据驱动为支撑,开启企业数字化转型之路(上)本文首发于财资一家微信公众号(微信IDTreasuryChina),关注公众号,获取更多财资知识。数据是一种宝贵的资源。数据资源是数据的自然维度,可通过数字文字图像以及计算机代码等人工智能板块这5大人工智能公司有望开启新一轮行情,未来可期五到十年内会有很多人工智能新的应用出来,你会发现很多新产品新服务,但是从这个学术界来讲,或者说最底层的技术来讲,不会有太大的变化。通常大家把握这样一个规律就好,当在计算机科学这个领长期耳鸣人可以戴什么助听器?您好,耳鸣是可以戴助听器的,可以去医院做进一步的检查,一定要早发现早治疗,如果严重是需要进行住院治疗的,平时一定要放松心态,保证一个良好的心情,要多喝白开水,不要感冒不要上火。若耳2022年3月起会不会回到纸币时代?最近几天时间有一些媒体在网上传,从2022年3月1日起,个人将不能使用微信以及支付宝收款,因此很多人都担心,从2022年3月之后,大家会不会回到纸币时代。在这先给大家吃一个定心丸,为什么戴了助听器感觉头顶上部发闷?戴上助听器觉得闷,堵,首要思考是发生堵耳效应。堵耳效应的发生是指正本应当经由外道软骨有些发泄出去的能量,如今由于助听器的阻挡不能开释出去,最后气导和骨导这两有些剩余能量叠加在一起,