python 多线程初试 与logger模块

对线程的一些理解:

一个程序为一个进程(process),一个进程下可以有多个线程(threading),至少有一个线程。

线程是最小的运行单位,多个线程共享一个进程的所有资源,每个线程执行不同的任务。

看到一个形象的解释是,进程是一个房子,里面的人是线程。如果有多个人的话,许多人共享房子里的资源。有时某些资源在一段时间里只能一个人使用(比如厕所),某些资源在一段时间里只能由固定数量的人使用(比如厨房在一段时间里最多容纳3个人)。这里又涉及到‘锁’的概念,这篇文章暂时没有涉及到。


从代码里来解释,python使用 线程 主要是使用threading模块,这段代码里也涉及到了logger模块的初步使用。

我在这里也会详细记录logging模块的使用方法

import logging
import threading
import time


def get_logger():
    logger = logging.getLogger("threading_eg")
    logger.setLevel(logging.WARNING)
    fh = logging.FileHandler("C:\\Users\Administrator\Desktop\python笔记\\threading.log")
    fmt = '%(asctime)s - %(name)s - %(processName)s - %(threadName)s - %(levelname)s - %(message)s'
    formatter = logging.Formatter(fmt)
    fh.setFormatter(formatter)
    logger.addHandler(fh)
    return logger


def doubler(number, logger):
    logger.debug("xxxx")
    logger.info("aaaa")
    logger.warning("bbbb")
    logger.error("cccc")

    result = number * 2
    time.sleep(5)
    logger.debug('yyyy: {}'.format(
        result))


logger = get_logger()
thread_names = ['Mike', 'George', 'Wanda', 'Dingbat', 'Nina']
for i in range(5):
    my_thread = threading.Thread(
        target=doubler, name=thread_names[i], args=(i, logger))
    my_thread.start()

1.先看第一个函数,get_logger

这个函数主要是构造一个logger对象,并设置logger的的各种信息,然后返回该对象。

第一行代码用getLogger方法构造一个logger对象,参数为该logger对象的名字。

第二行设置logger的 ‘日志等级’,我对其的理解是:日志需要输出什么等级的信息。

        比如,我设置的等级是WARNING,那么最后输出的信息只会包含warning信息和error信息。

        如果设置的等级是DEBUG,那么所有信息都会显示。

        日志等级主要有 DEBUG,INFO,WARNING,ERROR,CRITICAL 这几个。

第三行构造了一个handler对象,其内涵是将日志信息输入到什么地方去。handler对象有很多,这里是FileHandler,即是将日志信息输入到文件中去。最后一般都还要和addHandler方法配合使用,将handler加到logger对象去。

        logging.FileHandler(filename, mode='a', encoding=None, delay=False),mode为写入模式。

        其他handler可以参考这篇博客:

        http://blog.csdn.net/yypsober/article/details/51800120

第4~6行主要是设置handler对象的格式,fmt字符串,主要是这是输出哪些信息,第5行构造一个formatter对象,第六行设置handler的格式。

        fmt具有固定的格式,包含logging模块的其他的信息也可以在这篇文章里寻找:

        https://www.cnblogs.com/qianyuliang/p/7234217.html

        对这里fmt的内容稍微解释下:

        第一个即是运行时间,第二个是logger的名字,后面是进程名与线程名等等


2.再看第二个函数 doubler

    这个函数主要是接受一个数字和一个logger对象,将数字翻倍,然后在logger中输入一些信息。

    第1~4行是往logger的message里输入一些信息方法,与logger的日志等级对应。

    比如,这里已经输入了四种信息,debug,info,warning,error。这些信息会输入到fmt中的message中。

    logger的日志等级就决定了输出哪些等级的信息。

    后三行将数字翻倍,然后强制等待5s,最后再debug输入翻倍的信息。

3.看程序最后一段

    第一行构造前面设置好格式的logger对象,第二行是线程的名字。

    后一部分构造循环,用threading库的Thread方法构造线程:

    target为目标,即线程要做的内容。

    name为线程名字

    args为目标函数的参数,必须为元组对象,从左到右一一对应目标函数的参数。



结果:


由于日志等级为WARNING,所以只输出了warning与error传入的信息,如果将日志等级该位DEBUG,结果如下:



**************************************

现在来解释一下代码中出现的强制等待,与多线程。


将日志等级设为DEBUG,doubler函数改成如下:

def doubler(number, logger):
    logger.debug("xxxx")
    result = number * 2
    logger.debug('yyyy: {}'.format(
        result))

运行结果如下:



如果在代码里加上一句sleep:

def doubler(number, logger):
    logger.debug("xxxx")
    result = number * 2
    time.sleep(5)
    logger.debug('yyyy: {}'.format(
        result))

执行结果如下:


这个time.sleep充分体现了线程之间并行运行的。没加之前,代码运行到最后一行,线程启动,很快完成了doubler函数,所以第一次结果中,xxxx与yyyy基本同时出现。加了sleep后,前面的线程运行完doubler输出xxxx时,需要等待5s,后面的线程在这5s内都运行了起来,所以结果是差不多同时输出了xxxx,后来又同时输出yyyy。

两个线程之间差的时间,只是代码运行的时间(在这个程序里,就是执行for循环内的时间)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值