• day 26 (configparser + logging + collections) 模块


    configparser模块

    该模块适用于配置文件的格式与windows ini文件类似,可以包含一个或多个节(section),每个节可以有多个参数(键=值)。

    创建文件

    来看一个好多软件的常见文档格式如下:

    复制代码
    [DEFAULT]    #  全局的组(组长) ,  下面的属性也是全局属性
    ServerAliveInterval = 45
    Compression = yes
    CompressionLevel = 9
    ForwardX11 = yes
      
    [bitbucket.org]    自定义的组名
    User = hg        自定义的option
      
    [topsecret.server.com]    自定义组名
    Port = 50022
    ForwardX11 = no
    复制代码

    如果想用python生成一个这样的文档怎么做呢?

    复制代码import configparser    #首先导入configparser模块  
    config = configparser.ConfigParser()  #实例化一个对象
    
    config["DEFAULT"] = {'ServerAliveInterval': '45',    #根据创建的对象来设置组名和option。
    'Compression': 'yes',          DEFAULT,在配置文件中有关键词的作用。(生命全局) 'CompressionLevel': '9', 'ForwardX11':'yes' } config['bitbucket.org'] = {'User':'hg'} config['topsecret.server.com'] = {'Host Port':'50022','ForwardX11':'no'} with open('example.ini', 'w') as configfile:    最后一步打开文件,写入文件。否则不会生效 config.write(configfile)
    复制代码

    查找文件

    复制代码
    import configparser
    
    config = configparser.ConfigParser()
    
    #---------------------------查找文件内容,基于字典的形式
    
    print(config.sections())        #  []    #得到了一个空列表,因为没有读取文件
    
    config.read('example.ini')
    
    print(config.sections())        #   ['bitbucket.org', 'topsecret.server.com']  #这一次读取了文件,所以打印出所有的组名
    
    print('bytebong.com' in config) # False    #判断组名是否在config这个对象中
    print('bitbucket.org' in config) # True
    
    
    print(config['bitbucket.org']["user"])  # hg    #打印相应组名中的option的值
    
    print(config['DEFAULT']['Compression']) #yes
    
    print(config['topsecret.server.com']['ForwardX11'])  #no
    
    
    print(config['bitbucket.org'])          #<Section: bitbucket.org>   #说明每一个组名是一个可迭代对象
    
    for key in config['bitbucket.org']:     # 注意,有default会默认default的键  #除了自身的optinon还会有全局的option
        print(key)
    
    print(config.options('bitbucket.org'))  # 同for循环,找到'bitbucket.org'下所有键
    
    print(config.items('bitbucket.org'))    #找到'bitbucket.org'下所有键值对
    
    print(config.get('bitbucket.org','compression')) # yes       get方法Section下的key对应的value
    复制代码

    增删改操作

    复制代码
    import configparser
    
    config = configparser.ConfigParser()
    
    config.read('example.ini')
    
    config.add_section('yuan')    在添加组名前,必须读取文件
    
    
    
    config.remove_section('bitbucket.org')    删除组名
    config.remove_option('topsecret.server.com',"forwardx11")    删除组名对应的 option
    
    
    config.set('topsecret.server.com','k1','11111')    找到对应组的option ,有则改之,无则添加
    config.set('yuan','k2','22222')
    
    config.write(open('new2.ini', "w"))    想要生效,必须写入文件

     

    logging模块

    logging 不会帮你自动添加日志的内容

    函数式简单配置

    import logging  
    logging.basicConfig(level = logging.DEBUG)    #加这一行的话默认全部打印,不加会默认从warning模式开始打印 logging.debug('debug message') logging.info('info message') logging.warning('warning message') logging.error('error message') logging.critical('critical message')

    默认情况下Python的logging模块将日志打印到了标准输出中,且只显示了大于等于WARNING级别的日志,这说明默认的日志级别设置为WARNING(日志级别等级CRITICAL > ERROR > WARNING > INFO > DEBUG),默认的日志格式为日志级别:Logger名称:用户输出消息。

    灵活配置日志级别,日志格式,输出位置:

    复制代码
    import logging  
    logging.basicConfig(level=logging.DEBUG,  
                        format='%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s',  
                        datefmt='%a, %d %b %Y %H:%M:%S',  
                        filename='/tmp/test.log',  
                        filemode='w')  
      
    logging.debug('debug message')  
    logging.info('info message')  
    logging.warning('warning message')  
    logging.error('error message')  
    logging.critical('critical message')
    复制代码

    编码格式不能设置

    不能同时输出到文件和屏幕

    配置参数:

    复制代码
    logging.basicConfig()函数中可通过具体参数来更改logging模块默认行为,可用参数有:
    
    filename:用指定的文件名创建FiledHandler,这样日志会被存储在指定的文件中。
    filemode:文件打开方式,在指定了filename时使用这个参数,默认值为“a”还可指定为“w”。
    format:指定handler使用的日志显示格式。
    datefmt:指定日期时间格式。
    level:设置rootlogger(后边会讲解具体概念)的日志级别
    stream:用指定的stream创建StreamHandler。可以指定输出到sys.stderr,sys.stdout或者文件(f=open(‘test.log’,’w’)),默认为sys.stderr。若同时列出了filename和stream两个参数,则stream参数会被忽略。
    
    format参数中可能用到的格式化串:
    %(name)s Logger的名字
    %(levelno)s 数字形式的日志级别
    %(levelname)s 文本形式的日志级别
    %(pathname)s 调用日志输出函数的模块的完整路径名,可能没有
    %(filename)s 调用日志输出函数的模块的文件名
    %(module)s 调用日志输出函数的模块名
    %(funcName)s 调用日志输出函数的函数名
    %(lineno)d 调用日志输出函数的语句所在的代码行
    %(created)f 当前时间,用UNIX标准的表示时间的浮 点数表示
    %(relativeCreated)d 输出日志信息时的,自Logger创建以 来的毫秒数
    %(asctime)s 字符串形式的当前时间。默认格式是 “2003-07-08 16:49:45,896”。逗号后面的是毫秒
    %(thread)d 线程ID。可能没有
    %(threadName)s 线程名。可能没有
    %(process)d 进程ID。可能没有
    %(message)s用户输出的消息
    复制代码

    logger对象配置

    复制代码
    import logging
    
    logger = logging.getLogger()
    # 创建一个handler,用于写入日志文件
    fh = logging.FileHandler('test.log',encoding='utf-8') 

    # 再创建一个handler,用于输出到控制台
    ch = logging.StreamHandler()
    formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
    fh.setLevel(logging.DEBUG)

    fh.setFormatter(formatter)
    ch.setFormatter(formatter)
    logger.addHandler(fh) #logger对象可以添加多个fh和ch对象 
    logger.addHandler(ch)

    logger.debug('logger debug message')
    logger.info('logger info message')
    logger.warning('logger warning message')
    logger.error('logger error message')
    logger.critical('logger critical message')
    复制代码

    logging库提供了多个组件:Logger、Handler、Filter、Formatter。Logger对象提供应用程序可直接使用的接口,Handler发送日志到适当的目的地,Filter提供了过滤日志信息的方法,Formatter指定日志显示格式。另外,可以通过:logger.setLevel(logging.Debug)设置级别,当然,也可以通过

    fh.setLevel(logging.Debug)单对文件流设置某个级别。

     简单配置
    import logging
    # 默认情况下 只显示 警告 及警告级别以上信息
    # logging.basicConfig(level=logging.DEBUG,
    # format='%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s',
    # datefmt='%a, %d %b %y %H:%M:%S',
    # filename = 'userinfo.log'
    # )
    # logging.debug('debug message') # debug 调试模式 级别最低
    # logging.info('info message') # info 显示正常信息
    # logging.warning('warning message') # warning 显示警告信息
    # logging.error('error message') # error 显示错误信息
    # logging.critical('critical message') # critical 显示严重错误信息

    # 编码格式不能设置
    # 不能同时输出到文件 和 屏幕

    # 配置logger对象
    import logging
    logger = logging.getLogger() # 实例化了一个logger对象

    fh = logging.FileHandler('test.log',encoding='utf-8') # 实例化了一个文件句柄
    sh = logging.StreamHandler()

    fmt = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
    fh.setFormatter(fmt) # 格式和文件句柄或者屏幕句柄关联
    sh.setFormatter(fmt)
    sh.setLevel(logging.WARNING)

    # 吸星大法
    logger.addHandler(fh) # 和logger关联的只有句柄
    logger.addHandler(sh)
    logger.setLevel(logging.DEBUG)

    logger.debug('debug message') # debug 调试模式 级别最低
    logger.info('info message') # info 显示正常信息
    logger.warning('warning message') # warning 显示警告信息
    logger.error('error message') # error 显示错误信息
    logger.critical('critical message')


    # logging
    # logging 是记录日志的模块
    # 它不能自己打印内容 只能根据程序员写的代码来完成功能
    # logging模块提供5中日志级别,从低到高一次:debug info warning error critical
    # 默认从warning模式开始显示
    # 只显示一些基础信息,我们还可以对显示的格式做一些配置

    # 简单配置 配置格式 basicCondfig
    # 问题:编码问题,不能同时输出到文件和屏幕

    # logger对象配置
    # 高可定制化
    # 首先创造logger对象
    # 创造文件句柄 屏幕句柄
    # 创造格式
    # 使用文件句柄和屏幕句柄 绑定格式
    # logger对象和句柄关联
    # logger.setLevel
    # 使用的时候 logger.debug










    collections模块

    在内置数据类型(dict、list、set、tuple)的基础上,collections模块还提供了几个额外的数据类型:Counter、deque、defaultdict、namedtuple和OrderedDict等。

    1.namedtuple: 生成可以使用名字来访问元素内容的tuple

    2.deque: 双端队列,可以快速的从另外一侧追加和推出对象

    3.Counter: 计数器,主要用来计数

    4.OrderedDict: 有序字典

    5.defaultdict: 带有默认值的字典

    namedtuple

    们知道tuple可以表示不变集合,例如,一个点的二维坐标就可以表示成:

    >>> p = (1, 2)

    但是,看到(1, 2),很难看出这个tuple是用来表示一个坐标的。

    这时,namedtuple就派上了用场:

    复制代码
    >>> from collections import namedtuple
    >>> Point = namedtuple('Point', ['x', 'y'])
    >>> p = Point(1, 2)
    >>> p.x
    1
    >>> p.y
    2
    复制代码

    似的,如果要用坐标和半径表示一个圆,也可以用namedtuple定义:

    #namedtuple('名称', [属性list]):
    Circle = namedtuple('Circle', ['x', 'y', 'r'])

    deque

    使用list存储数据时,按索引访问元素很快,但是插入和删除元素就很慢了,因为list是线性存储,数据量大的时候,插入和删除效率很低。

    deque是为了高效实现插入和删除操作的双向列表,适合用于队列和栈:

    >>> from collections import deque
    >>> q = deque(['a', 'b', 'c'])
    >>> q.append('x')
    >>> q.appendleft('y')
    >>> q
    deque(['y', 'a', 'b', 'c', 'x'])

    deque除了实现list的append()pop()外,还支持appendleft()popleft(),这样就可以非常高效地往头部添加或删除元素。

    OrderedDict

    使用dict时,Key是无序的。在对dict做迭代时,我们无法确定Key的顺序。

    如果要保持Key的顺序,可以用OrderedDict

    复制代码
    >>> from collections import OrderedDict
    >>> d = dict([('a', 1), ('b', 2), ('c', 3)])
    >>> d # dict的Key是无序的
    {'a': 1, 'c': 3, 'b': 2}
    >>> od = OrderedDict([('a', 1), ('b', 2), ('c', 3)])
    >>> od # OrderedDict的Key是有序的
    OrderedDict([('a', 1), ('b', 2), ('c', 3)])
    复制代码

    意,OrderedDict的Key会按照插入的顺序排列,不是Key本身排序:

    >>> od = OrderedDict()
    >>> od['z'] = 1
    >>> od['y'] = 2
    >>> od['x'] = 3
    >>> od.keys() # 按照插入的Key的顺序返回
    ['z', 'y', 'x']

    defaultdict 

    有如下值集合 [11,22,33,44,55,66,77,88,99,90...],将所有大于 66 的值保存至字典的第一个key中,将小于 66 的值保存至第二个key的值中。

    即: {'k1': 大于66 'k2': 小于66}
    values = [11, 22, 33,44,55,66,77,88,99,90]
    
    my_dict = {}
    
    for value in  values:
        if value>66:
            if my_dict.has_key('k1'):
                my_dict['k1'].append(value)
            else:
                my_dict['k1'] = [value]
        else:
            if my_dict.has_key('k2'):
                my_dict['k2'].append(value)
            else:
                my_dict['k2'] = [value]
    原生字典解决方法
    from collections import defaultdict
    
    values = [11, 22, 33,44,55,66,77,88,99,90]
    
    my_dict = defaultdict(list)
    
    for value in  values:
        if value>66:
            my_dict['k1'].append(value)
        else:
            my_dict['k2'].append(value)
    defaultdict字典解决方法

    使dict时,如果引用的Key不存在,就会抛出KeyError。如果希望key不存在时,返回一个默认值,就可以用defaultdict

    >>> from collections import defaultdict
    >>> dd = defaultdict(lambda: 'N/A')
    >>> dd['key1'] = 'abc'
    >>> dd['key1'] # key1存在
    'abc'
    >>> dd['key2'] # key2不存在,返回默认值
    'N/A'
    例2

    Counter

    Counter类的目的是用来跟踪值出现的次数。它是一个无序的容器类型,以字典的键值对形式存储,其中元素作为key,其计数作为value。计数值可以是任意的Interger(包括0和负数)。Counter类和其他语言的bags或multisets很相似。

    c = Counter('abcdeabcdabcaba')
    print c
    输出:Counter({'a': 5, 'b': 4, 'c': 3, 'd': 2, 'e': 1})
    其他详细内容 http://www.cnblogs.com/Eva-J/articles/7291842.html














  • 相关阅读:
    Clojure实现的简单短网址服务(Compojure、Ring、Korma库演示样例)
    android4.4系统解决“ERRORcouldn&#39;t find native method”方法
    JS window.open()属性
    网页视频播放器代码大全 + 21个为您的站点和博客提供的免费视频播放器
    理解Java的GC日志
    图像识别技术
    堆排序原理及算法实现(最大堆)
    什么是依赖注入
    Cocos2d-x3.1下实现相似iOS页面滑动指示圆点
    [Bootstrap] 6. Navigation
  • 原文地址:https://www.cnblogs.com/zsdbk/p/8918899.html
Copyright © 2020-2023  润新知