zoukankan      html  css  js  c++  java
  • Python学习第二模块笔记(函数和常用模块)

    1、匿名函数

    没有函数名的函数,使用lambda来创建。e.g:

    >>> a = lambda x:x*3
    >>> a(3)
    9
    
    >>> a = lambda n:print(n)
    >>> a("aaa")
    aaa
    
    a = map(lambda x: x*2, range(5))
    for i in a:
        print(i)
    结果:
    0
    2
    4
    6
    8
    #匿名函数与其他函数搭配使用

    2、内置函数

    内置函数

    abs():返回数字的绝对值

    all():判断给定的可迭代对象 iterable 中的所有元素是否不为 0、''、False 或者 iterable 为空,如果是返回 True,否则返回 False,e.g:

    >>> all([])
    True
    #空列表
    >>> all([0,1,2,3])
    False
    #0为False
    >>> all([1,2,"",4])
    False
    #空元素
    >>> all([1,2,3,4])
    True

    any():判断给定的可迭代对象 iterable 是否全部为空对象,如果都为空、0、false,则返回 False,如果不都为空、0、false,则返回 True,注意与all()的区别,e.g:

    >>> any([])
    False
    #空列表
    >>> any([0,1,2,3])
    True
    #一个为真即为真
    >>> any([1,2,"",4])
    True
    >>> any([1,2,3,4])
    True

    ascii():类似 repr() 函数, 返回一个表示对象的字符串, 但是对于字符串中的非 ASCII 字符则返回\x, \u 或 \U 编码的字符,e.g:

    >>> a = [1,2,3]
    >>> ascii(a)
    '[1, 2, 3]'

    bin():返回一个整数的二进制,e.g:

    >>> bin(10)
    '0b1010'

    bool():将给定参数转换为布尔类型,如果没有参数,返回 False,e.g:

    >>> bool(0)
    False
    >>> bool(1)
    True

    bytearray():返回一个新字节数组。这个数组里的元素是可变的,并且每个元素的值范围: 0 <= x < 256,

    • 如果传入参数为整数,则返回一个长度为 source 的初始化数组;
    • 如果传入参数为字符串,则按照指定的 encoding 将字符串转换为字节序列;
    • 如果传入参数为可迭代类型,则元素必须为[0 ,255] 中的整数;
    • 如果传入参数为与 buffer 接口一致的对象,则此对象也可以被用于初始化 bytearray;
    • 如果没有输入任何参数,默认就是初始化数组为0个元素。

    e.g:

    >>> bytearray()
    bytearray(b'')
    >>> bytearray([1,2,3])
    bytearray(b'\x01\x02\x03')
    >>> bytearray('a', 'utf-8')
    bytearray(b'a')

    bytes():返回一个新的 bytes 对象,该对象是一个 0 <= x < 256 区间内的整数不可变序列。它是 bytearray 的不可变版本,e.g:

    >>> bytes()
    b''
    >>> bytes([1,2,3])
    b'\x01\x02\x03'
    >>> bytes('a','utf-8')
    b'a'

    callable():检查一个对象是否是可调用,e.g:

    >>> callable(1)
    False
    >>> def hello():
    ...     pass
    ...
    >>> callable(hello)
    True

    chr():返回当前整数对应的ascii字符,e.g:

    classmethod:类相关函数,未学

    compile():将一个字符串编译为字节代码,语法如下:

    compile(source, filename, mode[, flags[, dont_inherit]])
    
    # source -- 字符串或者AST(Abstract Syntax Trees)对象
    # filename -- 代码文件名称,如果不是从文件读取代码则传递一些可辨认的值
    # mode -- 指定编译代码的种类。可以指定为 exec, eval, single
    # flags -- 变量作用域,局部命名空间,如果被提供,可以是任何映射对象
    # flags和dont_inherit是用来控制编译源码时的标志

    e.g:

    >>>str = "for i in range(0,5): print(i)" 
    >>> c = compile(str,'','exec') 
    >>> c
    <code object <module> at 0x10141e0b0, file "", line 1>
    >>> exec(c)
    0
    1
    2
    3
    4

    complex():创建一个值为 real + imag * j 的复数或者转化一个字符串或数为复数。如果第一个参数为字符串,则不需要指定第二个参数

    delattr():用于删除属性,delattr(x,'name') = del x.name

    dict():用于创建一个字典,e.g:

    >>> dict(a=1,b=2,c=3)
    {'a': 1, 'b': 2, 'c': 3}
    >>> dict(a='a',b='b')
    {'a': 'a', 'b': 'b'}

    dir():不带参数时,返回当前范围内的变量、方法和定义的类型列表;带参数时,返回参数的属性、方法列表。如果参数包含方法__dir__(),该方法将被调用。如果参数不包含__dir__(),该方法将最大限度地收集参数信息,e.g:

    >>> dir([])
    ['__add__', '__class__', '__contains__', '__delattr__', '__delitem__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__gt__', '__hash__', '__iadd__', '__imul__', '__init__', '__init_subclass__', '__iter__', '__le__', '__len__', '__lt__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__reversed__', '__rmul__', '__setattr__', '__setitem__', '__sizeof__', '__str__', '__subclasshook__', 'append', 'clear', 'copy', 'count', 'extend', 'index', 'insert', 'pop', 'remove', 'reverse', 'sort']

    divmod():把除数和余数运算结果结合起来,返回一个包含商和余数的元组,e.g:

    >>> divmod(10,3)
    (3, 1)

    enumerate():用于将一个可遍历的数据对象(如列表、元组或字符串)组合为一个索引序列,同时列出数据和数据下标,一般用在 for 循环当中,e.g:

    >>> for i in enumerate(['a','b','c']):
    ...     print(i)
    ...
    (0, 'a')
    (1, 'b')
    (2, 'c')

    eval():用来执行一个字符串表达式,并返回表达式的值,e.g:

    >>> eval('1+2')
    3
    >>> eval('[1,2,3]')
    [1, 2, 3]

    exec():执行储存在字符串或文件中的 Python 语句,相比于 eval,exec可以执行更复杂的 Python 代码,e.g:

    >>> exec('for i in range(3):print(i)')
    0
    1
    2

    filter():用于过滤序列,过滤掉不符合条件的元素,返回由符合条件元素组成的新列表。该函数接收两个参数,第一个为函数,第二个为可迭代对象,可迭代对象的每个元素作为参数传递给函数进行判,然后返回 True 或 False,最后将返回 True 的元素放到新列表中,e.g:

    def is_odd(n):
        return n % 2 == 1
    for i in filter(is_odd, range(10)):
        print(i)
    结果:
    1
    3
    5
    7
    9

    float():用于将整数和字符串转换成浮点数

    format():用于字符串的格式化输出,e.g:

    name = "Python"
    age = 28
    print("{}的年龄为{}".format(name, age))
    结果:
    Python的年龄为28

    frozenset():返回一个冻结的集合,冻结后集合不能再添加或删除任何元素

    getattr():用于返回一个对象属性值

    getattr(object, name[, default])
    #object -- 对象
    #name -- 字符串,对象属性
    #default -- 默认返回值,如果不提供该参数,在没有对应属性时,将触发 AttributeError

    globals():以字典类型返回当前位置的全部全局变量

    hasattr():用于判断对象是否包含对应的属性,e.g:

    >>> hasattr([],'append')
    True
    >>> hasattr([],'isdigit')
    False

    hash():获取取一个对象(字符串或者数值等)的哈希值,e.g:

    >>> hash('a')
    7807180544025395620

    help():用于查看函数或模块用途的详细说明

    hex():用于将10进制整数转换成16进制整数,e.g:

    >>> hex(10)
    '0xa'

    id():用于获取对象的内存地址

    input():用于获取控制台输入

    int():将字符串数字转换为整型

    isinstance():判断一个对象是否是一个已知的类型,e.g:

    >>> isinstance(a,int)
    True
    >>> isinstance(a,str)
    False
    >>> isinstance(a,(int,str,list))
    True
    #是元组中的一个是返回True

    issubclass():用于判断是否是子类

    iter():用于生成迭代器

    len():返回对象(字符、列表、元组等)长度或项目个数

    list():将元组转换为列表

    locals():以字典类型返回当前位置的全部局部变量

    map():接收一个函数和一个列表,并通过把函数依次作用在列表的每个元素上,得到一个新的列表并返回,e.g:

    >>> a = map(lambda x:x*2,range(5))
    >>> for i in a:
    ...     print(i)
    ...
    0
    2
    4
    6
    8

    max():返回给定参数的最大值

    memoryview():返回给定参数的内存查看对象(Momory view)。所谓内存查看对象,是指对支持缓冲区协议的数据进行包装,在不需要复制对象基础上允许Python代码访问

    min():返回给定参数的最小值

    next():返回可迭代对象的下一个值

    oct():将一个整数转换成八进制

    open():打开文件

    ord():chr()函数的反函数

    pow():返回 xy(x的y次方) 的值,e.g:

    >>> pow(1,2)
    1

    print():打印输出

    property() :在新式类中返回属性值

    range():创建整数列表

    repr():将对象转化为供解释器读取的字符串形式,e.g:

    >>> a = {'a':1,'b':2}
    >>> repr(a)
    "{'a': 1, 'b': 2}"

    reversed():反转可迭代对象,e.g:

    >>> a = [1,2,3]
    >>> list(reversed(a))
    [3, 2, 1]

    round():返回浮点数的四舍五入值

    set():创建一个集合

    setattr():对应函数getatt()用于设置属性值,该属性必须存在

    slice():实现切片对象,主要用在切片操作函数里的参数传递,e.g:

    >>> a = [1,2,3,4,5]
    >>> myslice = slice(2)
    >>> a[myslice]
    [1, 2]

    sorted():对可迭代对象排序

    staticmethod():返回函数的静态方法

    str():将对象转换成始于人阅读的字符串形式

    sum():对可迭代对象求和,e.g:

    >>> sum([1,2,3])
    6

    super():函数用于调用下一个父类(超类)并返回该父类实例的方法。super 是用来解决多重继承问题的,直接用类名调用父类方法在使用单继承的时候没问题,但是如果使用多继承,会涉及到查找顺序(MRO)、重复调用(钻石继承)等种种问题。MRO 就是类的方法解析顺序表, 其实也就是继承父类方法时的顺序表

    tuple():将列表转换成元组

    type():返回对象的数据类型,e.g:

    >>> type(1)
    <class 'int'>
    >>> type('1')
    <class 'str'>

    vars():返回对象的属性和属性值的字典对象

    zip():用于将可迭代的对象作为参数,将对象中对应的元素打包成一个个元组,然后返回由这些元组组成的列表。如果各个迭代器的元素个数不一致,则返回列表长度与最短的对象相同,利用 * 号操作符,可以将元组解压为列表,e.g:

    >>> a = [1,2,3]
    >>> b = [4,5,6]
    >>> list(zip(a,b))
    [(1, 4), (2, 5), (3, 6)]

    __import__():用于动态加载类和函数 。如果一个模块经常变化就可以使用 __import__() 来动态载入

    3、装饰器

    decorator,本质上是一个函数,用于装饰其他函数,为其他函数添加新的功能。

    装饰器需要遵循以下原则:

    • 不能修改被装饰函数的源代码
    • 不能修改被装饰函数的调用方式

    装饰器需要知识:

    • 函数即“变量”,函数名 = 函数体,必须先声明再调用
    • 高阶函数,满足以下条件之一 

                   a.把一个函数名当作实参传给另一个函数(实现在不修改被装饰函数源代码的情况下为其添加新功能)

                   b.返回值中包含函数(实现不修改函数的调用方式)

    • 嵌套函数,在一个函数的函数体内用def声明一个新的函数
    • 闭包,在一个内部函数里,对在外部作用域(不是全局作用域)的变量进行引用,这个内部函数就是闭包(closure)

    装饰器 = 高阶函数+嵌套函数+闭包

    def test():
        print("测试函数!")
    
    print(test)
    print(test())
    
    #结果(注意调用函数带括号与不带括号时的区别)
    <function test at 0x000001D23579AEA0>    # 不带括号指向函数的内存地址
    测试函数!    # 带括号执行函数
    None    # 函数的返回值,无return语句返回None

    e.g:

    #函数带一个参数例子
    #未加装饰器
    def test1(name):
        print("你的名字%s" % name)
    
    test1("Python")
    #结果
    你的名字Python
    
    #加上装饰器
    def deco(func):
        def test(x):
            print("装饰器例子。")
            func(x)
            print("结束。")
        return test
    
    
    @deco
    def test1(name):
        print("你的名字%s" % name)
    
    test1("Python")
    #结果
    装饰器例子。
    你的名字Python
    结束。
    #函数带多个参数
    def deco(func):
        def test(*args, **kwargs):
            print("装饰器例子。")
            func(*args, **kwargs)
            print("结束。")
        return test
    
    
    @deco
    def test1(name, age):
        print("你的名字%s,你的年龄%s" % (name, age))
    
    test1("Python", 28)
    #结果
    装饰器例子。
    你的名字Python,你的年龄28
    结束。
    #带参数的装饰器
    def deco(x):
        def test(func):
            def test1(*args, **kwargs):
                print("装饰器例子。")
                func(*args, **kwargs)
                print("结束。看看带参数的装饰器%s" % x)
            return test1
        return test
    
    
    @deco(1)
    def test2(name, age):
        print("你的名字%s,你的年龄%s" % (name, age))
    
    test2("Python", 28)
    #结果
    装饰器例子。
    你的名字Python,你的年龄28
    结束。看看带参数的装饰器1
    def login(func):
        def deco(*args, **kwargs):
            func(*args, **kwargs)
            name, pw = "abc", "abc123"
            username = input("请输入用户名-->")
            password = input("请输入密码-->")
            if username == name and password == pw:
                print("欢迎%s回来!" % username)
            else:
                print("用户名或密码错误!")
        return deco
    
    
    def welcome():
        print("欢迎你的到来!")
    
    
    @login
    def user():
        print("请登录-->")
    
    welcome()
    
    user()
    #结果
    欢迎你的到来!
    请登录-->
    请输入用户名-->abc
    请输入密码-->abc123
    欢迎abc回来!

    4、列表生成式

    生成列表,可以使代码更整洁,e.g:

    >>> a = [i*2 for i in range(5)]
    >>> a
    [0, 2, 4, 6, 8]
    #生成一个列表,列表成员为0-4依次乘于2

    5、生成器

    受内存限制,列表的容量有限,创建大量元素的列表需要的存储空间巨大,而且列表的元素是固定存在的,如果只访问前面的元素,那么后面的元素占用的空间就浪费了。

    生成器generator,一边循环一边计算的机制,只在调用时才生成相应的数据,只记住当前值,无法返回前面的值,只能下一个,将列表生成式的[]换成()就可以创建一个生成器,e.g:

    >>> a = (i*2 for i in range(5))
    >>> next(a)
    0
    >>> next(a)
    2
    >>> next(a)
    4
    #使用next()函数调用下一个值
    >>> for i in a:
    ...     print(i)
    ...
    6
    8
    #通过for循环调用,注意输出结果,因为已经使用next()函数调用了三个值,所以for循环只输出了最后两个值
    
    #另外一种next使用方法
    >>> a = (i*2 for i in range(5))
    >>> a.__next__()
    0
    >>> a.__next__()
    2
    >>> a.__next__()
    4
    #使用函数创建生成器
    
    #原函数
    def test():
        for i in range(4):
            print(i)
            
    test()
    #结果
    0
    1
    2
    3
    
    #创建生成器
    def test():
        for i in range(4):
            yield i
    
    data = test()
    
    print(next(data))
    print(next(data))
    print(next(data))
    print(next(data))
    #结果
    0
    1
    2
    3
    #生成器并行运算
    
    def test(name):
        while True:
            yield
            print("他的名字是%s" % name)
    
    
    def test1(name):
        a = test("JAVA")
        a.__next__()
        for i in range(3):
            print("我的名字是%s" % name)
            a.send(i)     # 回到上次yield中断的地方
    
    test1("Python")
    #结果
    我的名字是Python
    他的名字是JAVA
    我的名字是Python
    他的名字是JAVA
    我的名字是Python
    他的名字是JAVA

    6、迭代器

    可迭代对象(Iterable):所以可以直接作用于for循环的对象,如列表、字典、生成器等

    迭代器(Iterator):可以被next()函数调用并不断返回下一个值的对象,惰性计算序列,只有在需要返回值的时候才进行计算

    #可以使用isinstance()函数判断是否是可迭代对象或者迭代器
    
    #可以使用for循环的都是可迭代对象
    >>> from collections import Iterable
    >>> isinstance([],Iterable)
    True
    >>> isinstance({},Iterable)
    True
    >>> isinstance((i*2 for i in range(5)),Iterable)
    True
    
    #列表、字典无法使用next()函数,所以不是迭代器
    >>> from collections import Iterator
    >>> isinstance([],Iterator)
    False
    >>> isinstance({},Iterator)
    False
    
    #生成器可以使用next()函数,所以是迭代器
    >>> isinstance((i*2 for i in range(5)),Iterator)
    True
    #使用iter()函数可以把一个可迭代对象转换成迭代器
    >>> from collections import Iterator
    >>> isinstance(iter([]),Iterator)
    True

    7、软件目录开发规范

    Foo/
    |-- bin/    #存放项目的一些可执行文件
    |   |-- foo.py    #程序执行文件,调用main.py文件实现各种功能
    |
    |-- foo/    #存放项目的所有源代码(1) 源代码中的所有模块、包都应该放在此目录,不要置于顶层目录;(2) 其子目录tests/存放单元测试代码; (3) 程序的入口最好命名为main.py。
    |   |-- tests/
    |   |   |-- __init__.py
    |   |   |-- test_main.py
    |   |
    |   |-- __init__.py
    |   |-- main.py    #程序的主入口,负责调用其他模块
    |
    |-- docs/       #存放一些文档
    |
    |-- conf/    #存放配置文件
    |   |--conf.py
    |
    |-- setup.py    #安装、部署、打包的脚本
    |-- requirements.txt    #存放软件依赖的外部Python包列表
    |-- README

    8、Python模块及import的本质

    模块在本质上是.py文件,用来从逻辑上组织python代码,以实现某个功能

    包在本质上是一个带有__init__.py文件的目录,用来从逻辑上组织模块。导入包的本质即解释目录下的__init__.py文件。

    模块的导入方法

    import xxx
    
    from xxx import xxx
    
    from xxx import xxx as xxx
    #as可以将原模块名在导入的时候定义一个新名称

    import在本质上就是把import的模块中的代码解释一遍并赋值给模块名

    模块的分类:

    • 标准库(内置模块)
    • 开源模块(第三方模块)
    • 自定义模块(自己写的模块)
    #不同目录间模块调用
    #使用os,sys模块的功能
    #目录结构如下
    |--a/
    |  |--aa/
    |     |--aaa.py
    |
    |  |--bb/
    |     |--bbb.py
    #在aaa.py中需要调用bbb.py
    
    os.path.abspath(__file__)    #返回当前文件的绝对路径,在这里为a/aa/aaa.py
    os.path.dirname()   #返回当前文件所在的目录
    os.path.dirname(os.path.abspath(__file__))   #这里为a/aa
    os.path.dirname(os.path.dirname(os.path.abspath(__file__)))    #这里为a,已经可以找到bb了
    sys.path.append()    #将路径加入python搜索模块的路径列表中
    
    #代码如下
    import os
    import sys
    base_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
    sys.path.append(base_dir)
    from bb import bbb
    bbb.xxx()#调用bbb下的xxx方法

    9、Python标准库(内置模块)

    9.1、time和date time模块

    Python中表示时间的方式:

    • 时间戳,表示从1970年1月1日00:00:00开始按秒计算的偏移量
    • 格式化的时间字符串
    • 元组(struct_time),共九个元素

    UTC(世界协调时),格林威治时间,世界标准时间。中国位于东八区,即UTC+8

    import time
    
    #time.process_time()(time.clock()) 测量处理器运算时间,不包括sleep的时间,e.g:
    >>> time.process_time()
    0.109375
    
    #time.time() 返回当前时间戳,e.g:
    >>> time.time()
    1508682933.4166296
    
    #time.altzone 返回格林威治西部的夏令时地区的偏移秒数,如果该地区在格林威治东部会返回负值(如西欧,包括英国),对夏令时启用地区才能使用,e.g:
    >>> time.altzone
    -32400
    
    #time.asctime() 接受struct_time并返回时间格式“Sun Oct 22 22:40:53 2017”,e.g:
    >>> time.asctime(time.localtime())
    'Sun Oct 22 22:43:34 2017'
    
    #time.localtime() 返回本地时间的struct_time,e.g:
    >>> time.localtime()
    time.struct_time(tm_year=2017, tm_mon=10, tm_mday=22, tm_hour=22, tm_min=45, tm_sec=48, tm_wday=6, tm_yday=295, tm_isdst=0)
    
    #time.gmtime() 返回UTC时间的struct_time,e.g:
    >>> time.gmtime()
    time.struct_time(tm_year=2017, tm_mon=10, tm_mday=22, tm_hour=14, tm_min=47, tm_sec=12, tm_wday=6, tm_yday=295, tm_isdst=0)
    
    #time.ctime() 同time.asctime(),e.g:
    >>> time.ctime()
    'Sun Oct 22 22:49:55 2017'
    
    #time.strptime 将日期字符串转成struct_time,e.g:
    >>> time.strptime("2017/01/22","%Y/%m/%d")
    time.struct_time(tm_year=2017, tm_mon=1, tm_mday=22, tm_hour=0, tm_min=0, tm_sec=0, tm_wday=6, tm_yday=22, tm_isdst=-1)
    
    #time.mktime() 将struct_time转成时间戳,e.g:
    >>> time.mktime(time.localtime())
    1508684200.0
    
    #time.strftime() 将struct_time转成指定的字符串格式,e.g:
    >>> time.strftime("%Y-%m-%d %H:%M:%S",time.localtime())
    '2017-10-22 22:59:33'
    #格式:
    # %a    本地(locale)简化星期名称    
    # %A    本地完整星期名称    
    # %b    本地简化月份名称    
    # %B    本地完整月份名称    
    # %c    本地相应的日期和时间表示    
    # %d    一个月中的第几天(01 - 31)    
    # %H   一天中的第几个小时(24小时制,00 - 23)    
    # %I     第几个小时(12小时制,01 - 12)    
    # %j     一年中的第几天(001 - 366)    
    # %m   月份(01 - 12)    
    # %M   分钟数(00 - 59)    
    # %p    本地am或者pm的相应符
    # %S    秒(01 - 61)
    # %U    一年中的星期数。(00 - 53星期天是一个星期的开始。)第一个星期天之前的所有天数都放在第0周。
    # %w    一个星期中的第几天(0 - 6,0是星期天)
    # %W   和%U基本相同,不同的是%W以星期一为一个星期的开始。    
    # %x     本地相应日期    
    # %X    本地相应时间    
    # %y     去掉世纪的年份(00 - 99)    
    # %Y    完整的年份    
    # %Z    时区的名字(如果不存在为空字符)    
    # %%    ‘%’字符
    #时间加减
    import datetime
    
    #datetime.datetime.now() 
    >>> print(datetime.datetime.now())
    2017-10-22 23:13:54.766792
    
    #datetime.date.fromtimestamp() 时间戳直接转成日期格式
    >>>>>> print(datetime.date.fromtimestamp(time.time()))
    2017-10-22
    
    #当前时间+3天
    >>> print(datetime.datetime.now() + datetime.timedelta(3))
    2017-10-25 23:14:43.124703
    
    #当前时间-3天
    >>> print(datetime.datetime.now() + datetime.timedelta(-3))
    2017-10-19 23:15:31.525936
    
    #当前时间+3小时
    >>> print(datetime.datetime.now() + datetime.timedelta(hours=3))
    2017-10-23 02:17:01.242468
    
    #当前时间+30分钟
    >>> print(datetime.datetime.now() + datetime.timedelta(minutes=30))
    2017-10-22 23:47:34.411346
    
    #时间替换
    >>> c_time  = datetime.datetime.now()
    >>> print(c_time)
    2017-10-22 23:19:10.420363
    >>> print(c_time.replace(minute=3,hour=2))
    2017-10-22 02:03:10.420363

    time

    9.2、random模块

    用于生成一个随机数

    import random
    
    #random.random() 生成一个0到1的随机浮点数,e.g:
    >>> random.random()
    0.11953524555173556
    >>> random.random()
    0.43441252324763446
    >>> random.random()
    0.2674464150139263
    
    #random.randint() 生成一个指定范围的随机整数,e.g:
    >>> random.randint(2,9)
    8
    >>> random.randint(2,9)
    3
    >>> random.randint(2,9)
    8
    
    #random.randrange() 从指定范围内,按指定基数递增的集合中获取一个随机数,e.g:
    >>> random.randrange(0,20,2)
    4
    >>> random.randrange(0,20,2)
    2
    >>> random.randrange(0,20,2)
    12
    
    #random.choice() 从序列中获取一个随机元素,e.g:
    >>> random.choice("I am Python")
    'I'
    >>> random.choice("I am Python")
    ' '
    >>> random.choice("I am Python")
    'y'
    >>> random.choice([1,3,5,7,9])
    5
    >>> random.choice([1,3,5,7,9])
    7
    >>> random.choice([1,3,5,7,9])
    3
    
    #random.sample() 从指定序列中随机获取指定长度的片段,e.g:
    >>> random.sample([1,3,5,7,9,11,13,15,17,19],3)
    [7, 19, 15]
    >>> random.sample([1,3,5,7,9,11,13,15,17,19],3)
    [9, 7, 15]
    >>> random.sample([1,3,5,7,9,11,13,15,17,19],3)
    [11, 9, 3]

    9.3、os模块和sys模块

    #os模块
    import os
    
    #os.getcwd() 获取当前工作目录,即当前python脚本工作的目录路径,e.g:
    >>> os.getcwd()
    'C:\\Users\\MAIMAI'
    
    #os.chdir() 改变当前脚本工作目录,e.g:
    >>> os.chdir(r"d:")
    >>> os.getcwd()
    'D:\\'
    
    #os.curdir 返回当前目录: ('.'),e.g:
    >>> os.curdir
    '.'
    
    #os.pardir  获取当前目录的父目录字符串名:('..'),e.g:
    >>> os.pardir
    '..'
    
    #os.makedirs() 可生成多层递归目录,e.g:
    >>> os.makedirs(r"d:\a\b\c")
    
    #os.removedirs() 若目录为空,则删除,并递归到上一级目录,如若也为空,则删除,依此类推
    
    #os.mkdir() 生成单级目录,e.g:
    >>> os.mkdir(r"d:\d")
    >>> os.mkdir(r"d:\f\d")
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    FileNotFoundError: [WinError 3] 系统找不到指定的路径。: 'd:\\f\\d'    # 只能生成单级目录,上级目录不存在时报错
    
    #os.rmdir() 删除单级空目录,若目录不为空则无法删除,报错
    
    #os.listdir() 列出指定目录下的所有文件和子目录,包括隐藏文件,并以列表方式打印,e.g:
    >>> os.listdir(r"d:\a")
    ['b', 'c', 'd']
    
    #os.remove() 删除一个文件
    
    #os.rename() 重命名文件/目录,e.g:
    >>> os.listdir(r"d:\a")
    ['b', 'c', 'd']
    >>> os.rename(r"d:\a\b",r"d:\a\e")
    >>> os.listdir(r"d:\a")
    ['c', 'd', 'e']
    
    #os.stat() 获取文件/目录信息,e.g:
    >>> os.stat(r"d:\a")
    os.stat_result(st_mode=16895, st_ino=11821949021849245, st_dev=520988, st_nlink=1, st_uid=0, st_gid=0, st_size=0, st_atime=1508687570, st_mtime=1508687570, st_ctime=1508687154)
    
    #os.sep 输出操作系统特定的路径分隔符,win下为"\\",Linux下为"/"
    
    #os.linesep 输出当前平台使用的行终止符,win下为"\t\n",Linux下为"\n"
    
    #os.pathsep 输出用于分割文件路径的字符串
    
    #os.name 输出字符串指示当前使用平台。win->'nt'; Linux->'posix'
    
    #os.system() 运行shell命令,直接显示,e.g:
    >>> os.system("ping www.baidu.com")
    
    正在 Ping www.a.shifen.com [183.232.231.173] 具有 32 字节的数据:
    来自 183.232.231.173 的回复: 字节=32 时间=23ms TTL=52
    来自 183.232.231.173 的回复: 字节=32 时间=22ms TTL=52
    来自 183.232.231.173 的回复: 字节=32 时间=21ms TTL=52
    来自 183.232.231.173 的回复: 字节=32 时间=24ms TTL=52
    
    183.232.231.173 的 Ping 统计信息:
        数据包: 已发送 = 4,已接收 = 4,丢失 = 0 (0% 丢失),
    往返行程的估计时间(以毫秒为单位):
        最短 = 21ms,最长 = 24ms,平均 = 22ms
    0
    
    #os.environ 获取系统环境变量
    
    #os.path.abspath() 返回规范化的绝对路径
    
    #os.path.split() 将路径分割成目录和文件名二元组返回,e.g:
    >>> os.path.split(r"d:\a")
    ('d:\\', 'a')
    
    #os.path.dirname() 返回文件所在的目录,其实就是os.path.split()的第一个元素
    
    #os.path.basename() 返回目录/文件最后的名称,如何path以/或\结尾,那么就会返回空值。即os.path.split(path)的第二个元素,e.g:
    >>> os.path.basename(r"d:\a")
    'a'
    
    #os.path.exists() 存在,返回True;不存在,返回False,e.g:
    >>> os.path.exists(r"d:\a")
    True
    
    #os.path.isabs() 如果是绝对路径,返回True,e.g:
    >>> os.path.isabs(r"d:\a")
    True
    
    #os.path.isfile()  如果是一个存在的文件,返回True,否则返回False,e.g:
    >>> os.path.isfile(r"d:\a")
    False
    >>> os.path.isfile(r"d:\a\a.txt")
    True
    
    #os.path.isdir() 如果是一个存在的目录,则返回True,否则返回False,e.g:
    >>> os.path.isdir(r"d:\a")
    True
    
    #os.path.join() 将多个路径组合后返回,第一个绝对路径之前的参数将被忽略,e.g:
    >>> os.path.join(r"d:",r"\a",r"b",r"c")
    'd:\\a\\b\\c'
    
    #os.path.getatime() 返回所指向的文件或者目录的最后存取时间
    
    #os.path.getmtime() 返回所指向的文件或者目录的最后修改时间

    os模块补充

    #os.walk() os.walk() 方法用于通过在目录树种游走输出在目录中的文件名,向上或者向下。
    #os.walk(top[, topdown=True[, onerror=None[, followlinks=False]]])
    #top -- 根目录下的每一个文件夹(包含它自己), 产生3-元组 (dirpath, dirnames, filenames)【文件夹路径, 文件夹名字[列表], 文件名[列表]】。
    #topdown --可选,为True或者没有指定, 一个目录的的3-元组将比它的任何子文件夹的3-元组先产生 (目录自上而下)。如果topdown为 False, 一个目录的3-元组将比它的任何子文件夹的3-元组后产生 (目录自下而上)。
    #onerror -- 可选,是一个函数; 它调用时有一个参数, 一个OSError实例。报告这错误后,继续walk,或者抛出exception终止walk。
    #followlinks -- 设置为 true,则通过软链接访问目录。
    #e.g:
    for dirpath, dirname, filename in os.walk(r"f:"):
        print(dirpath, dirname, filename)
    sys模块
    
    import sys
    
    #sys.argv 命令行参数List,第一个元素是程序本身路径,e.g:
    import sys
    print(sys.argv[1:])
    --->test.py
    f:\python>python test.py 1 2 3
    ['1', '2', '3']
    
    #sys.exit() 引发一个 SystemExit异常,若没有捕获这个异常,Python解释器会直接退出,捕获这个异常可以做一些额外的清理工作。0为正常退出,其他数值(1-127)为不正常,可抛异常事件供捕获
    
    #sys.version 获取Python解释器的版本信息
    >>> sys.version
    '3.6.2 (v3.6.2:5fd33b5, Jul  8 2017, 04:57:36) [MSC v.1900 64 bit (AMD64)]'
    
    #sys.path 返回列表形式的模块的搜索路径,
    
    #sys.platform 返回操作系统的名称
    
    #sys.stdout.write 输出,类似print

    9.4、shutil模块

    高级的文件、文件夹、压缩包处理模块

    import shutil
    
    #shutil.copyfileobj(fsrc, fdst[, length]) 将文件内容拷贝到另一个文件中,可以部分内容,需要先用open打开文件
    
    #shutil.copyfile(src, dst) 拷贝文件,不用先open
    
    #shutil.copymode(src, dst) 仅拷贝权限,内容、组、用户均不变
    
    #shutil.copystat(src, dst) 拷贝状态的信息,包括权限、组、用户、时间等
    
    #shutil.copy(src, dst) 拷贝文件和仅权限
    
    #shutil.copy2(src, dst) 拷贝文件和文件的所有状态信息
    
    #shutil.ignore_patterns(*patterns)
    #shutil.copytree(src, dst, symlinks=False, ignore=None) 递归的去拷贝文件
    #e.g:copytree(source, destination, ignore=ignore_patterns('*.pyc', 'tmp*'))
    
    #shutil.rmtree(path[, ignore_errors[, onerror]]) 递归的去删除文件
    
    #shutil.move(src, dst) 递归的去移动文件
    
    #shutil.make_archive(base_name, format,...) 创建压缩包并返回文件路径
    # base_name: 压缩包的文件名,也可以是压缩包的路径。只是文件名时,则保存至当前目录,否则保存至指定路径
    #  format: 压缩包种类,“zip”, “tar”, “bztar”,“gztar”
    #  root_dir: 要压缩的文件夹路径(默认当前目录)
    #  owner: 用户,默认当前用户
    #  group: 组,默认当前组
    # logger: 用于记录日志,通常是logging.Logger对象

    9.5、json、pickle和shelve模块

    json模块用来编码和解码JSON对象,只支持简单的数据类型,如列表、字典等

    import json
    
    #json.dumps 将Python对象编码成JSON字符串
    #json.loads 将JSON字符串解码成Python对象
    
    #json.dump 将Python对象编码成JSON字符串并写入文件
    #json.load 从文件中读取JSON字符串并解码成Python对象
    
    #json只支持简单的数据类型,如列表、字典等

    pickle模块用于python特有的类型和python的数据类型间进行转换,可序列化python所有数据类型

    import pickle
    
    #pickle.dumps 序列化
    #pickle.loads 反序列化
    
    #pickle.dump 写入文件
    #pickle.load 从文件中读取
    
    #存储的是二进制文件,open文件时应该使用rb、wb、ab模式

    shelve模块通过键值对的形式对内存数据进行文件持久化的模块,可以持久化任何pickle可支持的python数据格式,e.g:

    import shelve
    
    a = [1, 2, 3]
    
    f = shelve.open("test")
    f["test"] = a
    f.close()
    #将列表持久化保存
    f1 = shelve.open("test")
    print(f1["test"])
    f1.close()
    #通过键从文件中读取列表
    
    #结果
    [1, 2, 3]

    9.6、xml处理模块

    用于处理xml文件,需导入xml.etree.ElementTree模块。

    #以下是一个xml文件的内容
    
    <?xml version="1.0"?>
    <data>
        <country name="Liechtenstein">
            <rank updated="yes">2</rank>
            <year>2008</year>
            <gdppc>141100</gdppc>
            <neighbor name="Austria" direction="E"/>
            <neighbor name="Switzerland" direction="W"/>
        </country>
        <country name="Singapore">
            <rank updated="yes">5</rank>
            <year>2011</year>
            <gdppc>59900</gdppc>
            <neighbor name="Malaysia" direction="N"/>
        </country>
        <country name="Panama">
            <rank updated="yes">69</rank>
            <year>2011</year>
            <gdppc>13600</gdppc>
            <neighbor name="Costa Rica" direction="W"/>
            <neighbor name="Colombia" direction="E"/>
        </country>
    </data>
    #xml文件的读取
    
    import xml.etree.ElementTree as xml_ET  # 模块名太长,改个名
    
    tree = xml_ET.parse("test.xml")
    root = tree.getroot()   # <data></data>包起来的内容
    print(root.tag)    # 打印root标签
    
    #结果
    data
    import xml.etree.ElementTree as xml_ET  # 模块名太长,改个名
    
    tree = xml_ET.parse("test.xml")
    root = tree.getroot()   # <data></data>包起来的内容
    
    for child in root:    # 遍历整个xml文件
        print(child.tag, child.attrib)    #读取标签及属性
    
    #结果
    country {'name': 'Liechtenstein'}
    country {'name': 'Singapore'}
    country {'name': 'Panama'}
    
    import xml.etree.ElementTree as xml_ET  # 模块名太长,改个名
    
    tree = xml_ET.parse("test.xml")
    root = tree.getroot()   # <data></data>包起来的内容
    
    for child in root:    # 遍历整个xml文件
        for i in child:    # 遍历<country></country>包起来的内容
            print(i.tag, i.text)    # 读取标签及标签包起来的内容
    
    #结果
    rank 2
    year 2008
    gdppc 141100
    neighbor None
    neighbor None
    rank 5
    year 2011
    gdppc 59900
    neighbor None
    rank 69
    year 2011
    gdppc 13600
    neighbor None
    neighbor None
    
    import xml.etree.ElementTree as xml_ET  # 模块名太长,改个名
    
    tree = xml_ET.parse("test.xml")
    root = tree.getroot()   # <data></data>包起来的内容
    
    for node in root.iter("year"):  # 只遍历year节点
        print(node.tag, node.text)     # 打印标签及标签包起来的内容
    
    #结果
    year 2008
    year 2011
    year 2011
    #xml文件的修改
    
    import xml.etree.ElementTree as xml_ET
    
    tree = xml_ET.parse("test.xml")
    root = tree.getroot()
    
    for node in root.iter("year"):    # 修改year节点
        new_year = int(node.text) + 1
        node.text = str(new_year)
        node.set("updated", "yes")    # <year>标签修改成<year updated="yes">
    
    tree.write("test.xml")    # 修改内容写入xml文件
    
    # 删除node
    for country in root.findall("country"):
        rank = int(country.find("rank").text)   # 读取<rank></rank>中的内容
        if rank > 50:
            root.remove(country)    # 删除符合条件的country
    
    tree.write("output.xml")
    #创建xml文件
    
    import xml.etree.ElementTree as xml_ET
    
    new_xml = xml_ET.Element("namelist")    # 大标签
    name = xml_ET.SubElement(new_xml, "name", attrib={"enrolled": "yes"})   # 大标签下的子标签及子标签属性
    age = xml_ET.SubElement(name, "age", attrib={"checked": "no"})
    sex = xml_ET.SubElement(name, "sex")
    sex.text = '33'   # <sex>中的内容
    name2 = xml_ET.SubElement(new_xml, "name", attrib={"enrolled": "no"})
    age = xml_ET.SubElement(name2, "age")
    age.text = '19'
    
    et = xml_ET.ElementTree(new_xml)  # 生成文档对象
    et.write("test1.xml", encoding="utf-8", xml_declaration=True)   # 写入文件并打上xml标志
    
    xml_ET.dump(new_xml)  # 打印生成的格式

    9.7、PyYAML和configparser模块

    PyYAML模块用来处理ymal文档格式,具体用法参照http://pyyaml.org/wiki/PyYAMLDocumentation 

    configparser模块用于创建和修改常用的配置文件。

    #以下是一个配置文件的内容
    
    [DEFAULT]
    ServerAliveInterval = 45
    Compression = yes
    CompressionLevel = 9
    ForwardX11 = yes
     
    [bitbucket.org]
    User = hg
     
    [topsecret.server.com]
    Port = 50022
    ForwardX11 = no
    #创建配置文件
    
    import configparser
    
    config = configparser.ConfigParser()
    
    config["DEFAULT"] = {'ServerAliveInterval': '45',
                         'Compression': 'yes',
                         'CompressionLevel': '9'}
    
    config['bitbucket.org'] = {}
    config['bitbucket.org']['User'] = 'hg'
    
    config['topsecret.server.com'] = {}
    topsecret = config['topsecret.server.com']
    topsecret['Host Port'] = '50022'
    topsecret['ForwardX11'] = 'no'
    config['DEFAULT']['ForwardX11'] = 'yes'
    with open('example.ini', 'w') as configfile:
        config.write(configfile)
    # 实质上就是对字典的操作
    #读取配置文件
    
    import configparser
    
    config = configparser.ConfigParser()
    print(config.read("example.ini"))
    print(config.sections())
    print(config.options("bitbucket.org"))
    print(config.items("bitbucket.org"))    # 输出列表形式的键值对
    print(config.get("bitbucket.org", "compression"))   # 输出字符串
    print(config.getint("bitbucket.org", "compressionlevel"))   # 输出int
    print(config["bitbucket.org"]["user"])
    
    #结果
    ['example.ini']
    ['bitbucket.org', 'topsecret.server.com']
    ['user', 'serveraliveinterval', 'compression', 'compressionlevel', 'forwardx11']
    [('serveraliveinterval', '45'), ('compression', 'yes'), ('compressionlevel', '9'), ('forwardx11', 'yes'), ('user', 'hg')]
    yes
    9
    hg
    #修改配置文件
    
    import configparser
    
    config = configparser.ConfigParser()
    config.read("example.ini")    # 必须先读取配置文件
    
    config.add_section("baidu.com")    # 新建
    
    config.set("topsecret.server.com", "forwardx11", "yes")    # 修改
    
    config.remove_option("topsecret.server.com", "Port")   # 删除
    
    config.remove_section("topsecret.server.com")
    
    config.write(open("example.ini", "w"))    # 修改内容写入配置文件
    
    #检查一个section是否存在
    import configparser
    
    config = configparser.ConfigParser()
    config.read("example.ini")
    
    print(config.has_section("baidu.com"))
    
    #结果
    True

    9.8、hashlib模块

    用于加密的模块,提供了SHA1,SHA224,SHA256,SHA384,SHA512,MD5 算法,e.g:

    import hashlib
    
    m_b = hashlib.md5()
    m_b.update(b"I am Python")    # 直接传入字符串报错,需转编码
    print(m_b.hexdigest())    # 十六进制输出
    m_utf8 = hashlib.md5()
    m_utf8.update("I am Python".encode("utf-8"))    # 转utf-8
    print(m_utf8.hexdigest())
    
    b = hashlib.sha1()
    b.update(b"I am Python")
    print(b.hexdigest())
    
    zh_cn = hashlib.md5()
    zh_cn.update("我是Python".encode("utf-8"))    # 中文直接传utf-8
    print(zh_cn.hexdigest())
    
    #结果
    563f710d7f1020c8ee1c95f77650918a
    563f710d7f1020c8ee1c95f77650918a
    a1780aaa27454ce0a9ee7a7518405d8c72523843
    c46b544b85b64a0a45c6081e2fbacbaf

    hmac模块可对自定义的key和内容进行处理后再加密,e.g:

    import hmac
    
    a = hmac.new("我是Python".encode("utf-8"), "我是Python2".encode("utf-8"))
    print(a.hexdigest())
    
    #结果
    deb7cd3a5ac6169c841fdaaf8b10f384

    9.9、logging模块

    logging模块提供标准的日志接口,可存储各种格式的日志,logging的日志分为debug、info、warning、error、critical五个级别 ,

    • DEBUG:详细的信息,通常只出现在诊断问题上
    • INFO:确认一切按预期运行
    • WARNING:一个迹象表明,一些意想不到的事情发生了,或表明一些问题在不久的将来(例如。磁盘空间低”)。这个软件还能按预期工作。
    • ERROR:更严重的问题,软件没能执行一些功能
    • CRITICAL:一个严重的错误,这表明程序本身可能无法继续运行
    import logging
    
    logging.debug("debug")
    logging.info("info")
    logging.warning("warning")
    logging.error("error")
    logging.critical("critical")
    
    #结果
    WARNING:root:warning
    ERROR:root:error
    CRITICAL:root:critical
    #报警按级别显示,debug、info默认不显示
    
    logging.basicConfig(filename='test.log',level=logging.INFO) 
    #将日志写入文件,level定义记录的日志级别,低于该级别的日志不被记录
    
    logging.basicConfig(format='%(asctime)s %(message)s', datefmt='%m/%d/%Y %I:%M:%S %p')
    #为日志加上一些格式
    
    #日志格式具体如下
    # %(name)s               Logger的名字
    # %(levelno)s            数字形式的日志级别
    # %(levelname)s          文本形式的日志级别
    # %(pathname)s           调用日志输出函数的模块的完整路径名,可能没有
    # %(filename)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            用户输出的消息

    Python 使用logging模块记录日志涉及四个主要类:

    • logger提供了应用程序可以直接使用的接口
    • handler将(logger创建的)日志记录发送到合适的目的输出
    • filter提供了细度设备来决定输出哪条日志记录
    • formatter决定日志记录的最终输出格式
    logger

    每个程序在输出信息之前都要获得一个Logger,Logger通常对应了程序的模块名

    logging.getLogger():获得一个Logger

    Logger.setLevel():指定最低的日志级别,低于设置的级别将被忽略

    Logger.addFilter()、Logger.removeFilter():添加或删除指定的filter

    Logger.addHandler()、Logger.removeHandler():增加或删除指定的handler

    Logger.debug()、Logger.info()、Logger.warning()、Logger.error()、Logger.critical():可以设置的日志级别

    handler

    handler对象负责发送相关的信息到指定目的地。Python的日志系统有多种Handler可以使用。有些Handler可以把信息输出到控制台,有些Handler可以把信息输出到文件,还有些 Handler可以把信息发送到网络上。如果觉得不够用,还可以编写自己的Handler。可以通过addHandler()方法添加多个多handler

    Handler.setLevel():指定被处理的信息级别,低于设置级别的信息将被忽略
    Handler.setFormatter():给这个handler选择一个格式
    Handler.addFilter()、Handler.removeFilter():新增或删除一个filter对象

    常用Handler:

    1、logging.StreamHandler,使用这个Handler可以向类似与sys.stdout或者sys.stderr的任何文件对象(file object)输出信息。它的构造函数是:StreamHandler([strm]),其中strm参数是一个文件对象。默认是sys.stderr。

    2、logging.FileHandler,和StreamHandler类似,用于向一个文件输出日志信息。FileHandler会帮你打开这个文件。它的构造函数是:FileHandler(filename[,mode]),filename是文件名,必须指定一个文件名。mode是文件的打开方式,默认是“a”,即添加到文件末尾。

    3、logging.handlers.RotatingFileHandler,这个Handler类似于上面的FileHandler,但是它可以管理文件大小。当文件达到一定大小之后,它会自动将当前日志文件改名,然后创建一个新的同名日志文件继续输出。比如日志文件是chat.log。当chat.log达到指定的大小之后,RotatingFileHandler自动把文件改名为chat.log.1。不过,如果chat.log.1已经存在,会先把chat.log.1重命名为chat.log.2。。。最后重新创建 chat.log,继续输出日志信息。它的构造函数是:RotatingFileHandler( filename[, mode[, maxBytes[, backupCount]]]),其中filename和mode两个参数和FileHandler一样。maxBytes用于指定日志文件的最大文件大小。如果maxBytes为0,意味着日志文件可以无限大,这时上面描述的重命名过程就不会发生。backupCount用于指定保留的备份文件的个数。比如,如果指定为2,当上面描述的重命名过程发生时,原有的chat.log.2并不会被更名,而是被删除。
    4、logging.handlers.TimedRotatingFileHandler,这个Handler和RotatingFileHandler类似,不过,它没有通过判断文件大小来决定何时重新创建日志文件,而是间隔一定时间就 自动创建新的日志文件。重命名的过程与RotatingFileHandler类似,不过新的文件不是附加数字,而是当前时间。它的构造函数是:TimedRotatingFileHandler( filename [,when [,interval [,backupCount]]]),其中filename参数和backupCount参数和RotatingFileHandler具有相同的意义,interval是时间间隔,when参数是一个字符串。表示时间间隔的单位,不区分大小写。它有以下取值:
    S 秒
    M 分
    H 小时
    D 天
    W 每星期(interval==0时代表星期一)
    midnight 每天凌晨

    e.g:

    import logging
    
    logger = logging.getLogger("TESE")
    logger.setLevel(logging.DEBUG)
    # 获得一个logger并定义记录级别
    
    screen = logging.StreamHandler()
    screen.setLevel(logging.DEBUG)
    # 定义一个屏幕输出Handler并定义记录级别
    
    file = logging.FileHandler("test.log")
    file.setLevel(logging.DEBUG)
    # 定义一个文件输出Handler并定义记录级别
    
    formatter = logging.Formatter("%(asctime)s-%(levelname)s-%(filename)s")
    # 定义一个日志记录格式
    
    screen.setFormatter(formatter)
    file.setFormatter(formatter)
    # 为Handler指定记录格式
    
    logger.addHandler(screen)
    logger.addHandler(file)
    # 添加日志的Handler
    
    logger.debug("This is a debug_log")
    logger.info("This is a info_log")
    logger.warning("This is a warning_log")
    logger.error("This is a error_log")
    logger.critical("This is a critical_log")
    # 每个级别的输出信息
    
    #结果
    #屏幕输出
    2017-10-23 14:40:09,892-DEBUG-test.py
    2017-10-23 14:40:09,893-INFO-test.py
    2017-10-23 14:40:09,893-WARNING-test.py
    2017-10-23 14:40:09,893-ERROR-test.py
    2017-10-23 14:40:09,893-CRITICAL-test.py
    #信息同时写入test.log文件

    9.10、re模块

    re模块用于对正则表达式的操作。

    import re
    
    #常用匹配语法
    #re.match 从头开始匹配,e.g:
    >>> re.match("a","abc").group()
    'a'
    >>> re.match("b","abc").group()
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    AttributeError: 'NoneType' object has no attribute 'group'
    
    #re.search 匹配包含,e.g:
    >>> re.search("b","abc").group()
    'b'
    
    #re.findall 把所有匹配到的字符放到以列表中的元素返回,e.g:
    >>> re.findall("\w","abcdefg")
    ['a', 'b', 'c', 'd', 'e', 'f', 'g']
    
    #re.split 以匹配到的字符当做列表分隔符,e.g:
    >>> re.split("b","abc")
    ['a', 'c']
    
    #re.sub 匹配字符并替换
    >>> re.sub("b","c","ab")
    'ac
    #常用正则表达式符号
    
    #"." 默认匹配除\n之外的任意一个字符,若指定flag DOTALL,则匹配任意字符,包括换行,e.g:
    >>> re.search(".","abcd").group()
    'a'
    >>> re.search(".","+-*/").group()
    '+'
    
    #"^" 匹配字符开头,若指定flags MULTILINE,这种也可以匹配上(r"^a","\nabc\neee",flags=re.MULTILINE),e.g:
    >>> re.search("^a","abc").group()
    'a'
    >>> re.search("^b","abc").group()
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    AttributeError: 'NoneType' object has no attribute 'group'
    
    #"$" 匹配字符结尾,若指定flags MULTILINE,re.search("foo$","bfoo\nsdfsf",flags=re.MULTILINE).group()也可以匹配上,e.g:
    >>> re.search("c$","abc").group()
    'c'
    >>> re.search("b$","abc").group()
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    AttributeError: 'NoneType' object has no attribute 'group'
    
    #"*" 匹配*号前的字符0次或多次,e.g:
    >>> re.findall("ab*","abcabcabc")
    ['ab', 'ab', 'ab']
    
    #"+" 匹配前一个字符1次或多次,e.g:
    >>> re.findall("a+","abcabcabc")
    ['a', 'a', 'a']
    
    #"?" 匹配前一个字符1次或0次
    
    #"{m}" 匹配前一个字符m次
    
    #"{n,m}" 匹配前一个字符n到m次
    
    #"[]" 匹配字符集中的任意一个字符。[^]表示取反。
    >>> re.search("[ad]","abc").group()
    'a'
    >>> re.findall("[^a]","abc")
    ['b', 'c']
    
    #"x|y" 匹配x或y的字符,e.g:
    >>> re.search("a|d","abc").group()
    'a'
    
    #"()" 分组匹配
    
    #"\A" 只从字符开头匹配,e.g:
    >>> re.search("\Aa","abc").group()
    'a'
    >>> re.search("\Ab","abc").group()
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    AttributeError: 'NoneType' object has no attribute 'group'
    
    #"\Z" 匹配字符结尾,同$
    
    #"\d" 匹配数字0-9
    
    #"\D" 匹配非数字
    
    #"\w" 匹配A-Z、a-z、0-9
    
    #"\W" 匹配非A-Z、a-z、0-9
    
    #"\s" 匹配空白字符、\t、\n、\r ,e.g:
    >>> re.search("\s","\nabc").group()
    '\n'
    
    #"(?P)" 分组匹配并生成一个字典,e.g:
    >>> re.search("(?P<a>a)(?P<b>b)(?P<c>c)","abc").groupdict()
    {'a': 'a', 'b': 'b', 'c': 'c'}
    
    #re.I(re.IGNORECASE):忽略大小写(括号内为完整写法)
    #re.M(MULTILINE):多行模式,改变'^'和'$'的行为
    #re.S(DOTALL):任意匹配模式,改变"."的行为

    9.11、subprocess模块

    subprocess模块用于与系统进行交互,通过子进程来执行系统指令。

    #以下在Linux下进行,Windows下结果有所不同
    
    #subprocess.run()推荐的常用方法
    >>> subprocess.run(["df", "-m"])
    文件系统        1M-块   已用   可用 已用% 挂载点
    udev             1953      0   1953    0% /dev
    tmpfs             395      6    390    2% /run
    /dev/sda1      499806 200207 274189   43% /
    tmpfs            1975     20   1956    1% /dev/shm
    tmpfs               5      1      5    1% /run/lock
    tmpfs            1975      0   1975    0% /sys/fs/cgroup
    tmpfs             395      1    395    1% /run/user/1000
    CompletedProcess(args=['df', '-m'], returncode=0)
    >>> subprocess.run("df -m", shell = True)
    文件系统        1M-块   已用   可用 已用% 挂载点
    udev             1953      0   1953    0% /dev
    tmpfs             395      6    390    2% /run
    /dev/sda1      499806 200207 274189   43% /
    tmpfs            1975     20   1956    1% /dev/shm
    tmpfs               5      1      5    1% /run/lock
    tmpfs            1975      0   1975    0% /sys/fs/cgroup
    tmpfs             395      1    395    1% /run/user/1000
    CompletedProcess(args='df -m', returncode=0)
    
    #subprocess.call()执行命令,返回命令执行结果及执行状态,成功为0,失败非0
    >>> subprocess.call(["df", "-h"])
    文件系统        容量  已用  可用 已用% 挂载点
    udev            2.0G     0  2.0G    0% /dev
    tmpfs           395M  6.0M  390M    2% /run
    /dev/sda1       489G  196G  268G   43% /
    tmpfs           2.0G   26M  2.0G    2% /dev/shm
    tmpfs           5.0M  4.0K  5.0M    1% /run/lock
    tmpfs           2.0G     0  2.0G    0% /sys/fs/cgroup
    tmpfs           395M   48K  395M    1% /run/user/1000
    0
    >>> subprocess.call(["df", "-t"])
    df:选项需要一个参数 -- t
    Try 'df --help' for more information.
    1
    
    #subprocess.check_call()执行命令,成功执行返回0,失败则抛出异常
    >>> subprocess.check_call(["df", "-m"])
    文件系统        1M-块   已用   可用 已用% 挂载点
    udev             1953      0   1953    0% /dev
    tmpfs             395      6    390    2% /run
    /dev/sda1      499806 200207 274188   43% /
    tmpfs            1975     18   1957    1% /dev/shm
    tmpfs               5      1      5    1% /run/lock
    tmpfs            1975      0   1975    0% /sys/fs/cgroup
    tmpfs             395      1    395    1% /run/user/1000
    0
    >>> subprocess.check_call(["df", "-t"])
    df:选项需要一个参数 -- t
    Try 'df --help' for more information.
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
      File "/usr/lib/python3.5/subprocess.py", line 581, in check_call
        raise CalledProcessError(retcode, cmd)
    subprocess.CalledProcessError: Command '['df', '-t']' returned non-zero exit status 1
    
    #subprocess.getstatusoutput()返回一个元组,第一个元素是执行状态,第二个元素是执行结果
    >>> subprocess.getstatusoutput(["df", "-h"])
    (0, '文件系统           1K-块      已用      可用 已用% 挂载点\nudev             1999728         0   1999728    0% /dev\ntmpfs             404424      6080    398344    2% /run\n/dev/sda1      511801088 205011900 280768172   43% /\ntmpfs            2022108     18836   2003272    1% /dev/shm\ntmpfs               5120         4      5116    1% /run/lock\ntmpfs            2022108         0   2022108    0% /sys/fs/cgroup\ntmpfs             404424        48    404376    1% /run/user/1000')
    
    #subprocess.getoutput()以字符串形式返回执行结果
    >>> subprocess.getoutput(["df", "-m"])
    '文件系统           1K-块      已用      可用 已用% 挂载点\nudev             1999728         0   1999728    0% /dev\ntmpfs             404424      6080    398344    2% /run\n/dev/sda1      511801088 205012144 280767928   43% /\ntmpfs            2022108     18836   2003272    1% /dev/shm\ntmpfs               5120         4      5116    1% /run/lock\ntmpfs            2022108         0   2022108    0% /sys/fs/cgroup\ntmpfs             404424        48    404376    1% /run/user/1000'
    
    #subprocess.check_output()
    >>> subprocess.check_output(["df", "-m"])
    b'\xe6\x96\x87\xe4\xbb\xb6\xe7\xb3\xbb\xe7\xbb\x9f        1M-\xe5\x9d\x97   \xe5\xb7\xb2\xe7\x94\xa8   \xe5\x8f\xaf\xe7\x94\xa8 \xe5\xb7\xb2\xe7\x94\xa8% \xe6\x8c\x82\xe8\xbd\xbd\xe7\x82\xb9\nudev             1953      0   1953    0% /dev\ntmpfs             395      6    390    2% /run\n/dev/sda1      499806 200208 274188   43% /\ntmpfs            1975     20   1956    1% /dev/shm\ntmpfs               5      1      5    1% /run/lock\ntmpfs            1975      0   1975    0% /sys/fs/cgroup\ntmpfs             395      1    395    1% /run/user/1000\n'
    #subprocess.Popen()subprocess模块的底层方法
    
    #可用参数
    # args:shell命令,可以是字符串或者序列类型(如:list,元组)
    # bufsize:指定缓冲。0 无缓冲,1 行缓冲,其他 缓冲区大小,负值 系统缓冲
    # stdin, stdout, stderr:分别表示程序的标准输入、输出、错误句柄
    # preexec_fn:只在Unix平台下有效,用于指定一个可执行对象(callable object),它将在子进程运行之前被调用
    # close_sfs:在windows平台下,如果close_fds被设置为True,则新创建的子进程将不会继承父进程的输入、输出、错误管道。所以不能将close_fds设置为True同时重定向子进程的标准输入、输出与错误(stdin, stdout, stderr)。
    # shell:同上
    # cwd:用于设置子进程的当前目录
    # env:用于指定子进程的环境变量。如果env = None,子进程的环境变量将从父进程中继承。
    universal_newlines:不同系统的换行符不同,True -> 同意使用 \n
    # startupinfo与createionflags只在windows下有效,将被传递给底层的CreateProcess()函数,用于设置子进程的一些属性,如:主窗口的外观,进程的优先级等等
    
    #e,g:
    subprocess.Popen(["df", "-m"], stdout = subprocess.PIPE)
  • 相关阅读:
    .net 面试题 没事多看看。。。。
    分享一下我记忆23种设计模式的方法 <转。。>
    再次写给我们这些浮躁的程序员 《搜集的。。。》
    C#验证邮箱,电话,手机,数字,英文,日期,身份证,邮编,网址,IP类.. (转后整理)
    javascript和jquery使用技巧集
    jQuery 增加 删除 修改select option .
    设计模式(二)
    JavaScript string 字符串类型的扩展方法
    26个jQuery使用技巧
    jBPM开发入门指南(1)
  • 原文地址:https://www.cnblogs.com/yu2006070/p/7641764.html
Copyright © 2011-2022 走看看