• 008-Python-模块


    1.模块

    1.1什么是模块

    一个模块就是一个包含了python定义和声明的文件,文件名就是模块名字加上.py的后缀;
    模块分为:

    1. 内置模块(内部定义的如time,os,sys等)
    2. 第三方模块(需要安装)
    3. 自定义模块(自己定义的)

    1.2为什么要使用模块

    如果你退出python解释器然后重新进入,那么你之前定义的函数或者变量都将丢失,因此我们通常将程序写到文件中以便永久保存下来,需要时就通过python test.py方式去执行,此时test.py被称为脚本script。
    随着程序的发展,功能越来越多,为了方便管理,我们通常将程序分成一个个的文件,这样做程序的结构更清晰,方便管理。这时我们不仅仅可以把这些文件当做脚本去执行,还可以把他们当做模块来导入到其他的模块中,实现了功能的重复利用,

    2.模块的使用

    2.1导入一个模块

    1. 导入一个系统模块;并引用这个模块;
    import time
    print(time.time())
    
    输出:
    1487571343.8582766
    

    2.2自定义一个模块并导入:

    1.模块就是一个包含了python定义和声明的文件,所以先创建一个cal.py的文件;

    [root@linux-node1 ~]# cat cal.py
    print("ok1")
    def add(x, y):
        return x+y
    def sub(x, y):
        return x-y
    print("ok2")
    

    2.在另一个文件test.py中使用import导入cal.py文件(在调用时需要加上cal.前缀)

    语法:import cal.py (默认py不写)
    [root@linux-node1 ~]# cat test.py
    import cal
    print(cal.sub(4, 5))
    print(cal.add(4, 5))
    
    
    输出:
    ok1
    ok2
    -1
    9
    

    3.在文件test.py中导入单个模块(在使用的时候,不需要加cal前缀);

    语法:from cal.py import 模块
    [root@linux-node1 ~]# cat test.py
    from cal import add
    from cal import sub
    print(sub(4, 5))
    print(add(4, 5))
    
    输出:
    ok1
    ok2
    -1
    9
    

    4.在文件test.py中导入所有模块(不建议这么使用,不能确定到底导入了什么模块,会产生模块覆盖);

    语法:from cal.py import *
    [root@linux-node1 ~]# cat test.py
    from cal import *
    print(sub(4, 5))
    print(add(4, 5))
    
    输出:
    ok1
    ok2
    -1
    9
    

    5.可以将导入的模块定义一个别名:
    语法:import 模块 as 别名

    [root@linux-node1 ~]# cat test.py
    import cal as abc
    print(abc.sub(4, 5))
    print(abc.add(4, 5))
    
    
    输出:
    ok1
    ok2
    -1
    9
    

    2.3自定义模块与调用模块不在同一个路径:

    1.在解释器和模块之间不在同一个目录,解释器在模块的上一层路径,如何调用模块;
    目录结构:

    └── 自定义模块       
        ├── __init__.py   
        ├── my_module   
        │   ├── __init__.py    
        │   └── cal.py            # 被调用者
        └── test.py               # 调用者
    

    语法:
    from 目录路径 import 被调用模块

    [root@linux-node1 ~]# cat test.py
    from my_module import cal
    print(cal.add(4, 5))
    
    输出:
    ok1
    ok2
    -1
    9
    

    常用内置标准模块

    1. time 时间模块
    2. timedate 时间模块
    3. random,string模块(生成随机字符串)
    4. os模块
    5. sys模块
    6. json & pickle 模块
    7. logging模块

    1.时间模块

    1.1导入时间模块

    import time
    

    1.2当前时间的时间戳

    print(time.time())
    输出:
    1487762678.2732341
    

    1.3返回与utc时间的时间差,以秒计算

    print(time.altzone)  
    输出:
    -32400
    

    1.4返回时间格式

    print(time.asctime())  
    输出:
    "Wed Feb 22 19:15:04 2017"
    

    1.5返回本地时间 的struct time对象格式

    print(time.localtime()) 
    输出:
    time.struct_time(tm_year=2017, tm_mon=2, tm_mday=22, tm_hour=19, tm_min=9, tm_sec=35, tm_wday=2, tm_yday=53, tm_isdst=0)
    
    可以调用
    
    f = time.localtime()
    print(f.tm_year,f.tm_mon)
    输出:
    2017 2
    

    1.6返回utc时间的struc时间对象格式

    print(time.gmtime())
    输出:
    time.struct_time(tm_year=2017, tm_mon=2, tm_mday=22, tm_hour=11, tm_min=19, tm_sec=54, tm_wday=2, tm_yday=53, tm_isdst=0)
    
    
    print(time.asctime(time.localtime()))
    Wed Feb 22 19:22:52 2017
    

    1.7自定义时间格式输出:

    print(time.strftime("%Y-%m-%d %H:%M:%S"))
    
    输出:
    2017-02-22 21:25:48
    

    1.8展现前一天的当前时间:

    string_1_struct = time.localtime(time.time()-86400)
    print(time.strftime("%Y-%m-%d %H:%M:%S", string_1_struct))
    
    输出:
    2017-02-21 21:30:44
    

    1.9将日期字符串转换成struct时间对象格式

    string_2_struct = time.strptime("2017-02-22 21:36:12", "%Y-%m-%d %H:%M:%S")
    print(string_2_struct)
    
    输出:
    time.struct_time(tm_year=2017, tm_mon=2, tm_mday=22, tm_hour=21, tm_min=36, tm_sec=12, tm_wday=2, tm_yday=53, tm_isdst=-1)
    

    1.10将时间的字符串格式转换为时间戳: 将时间字符串---》时间对象---》---》时间戳

    string_2_struct = time.strptime("2017-02-22 21:36:12", "%Y-%m-%d %H:%M:%S")
    print(time.mktime(string_2_struct))
    
    输出:
    1487770572.0
    

    如图:
    时间戳到时间格式输出转换
    1.11将时间戳转换为字符串格式: 将时间戳---》时间对象---》时间字符串

    zifuchuan = time.gmtime(148770000.0)
    print(zifuchuan)
    print(time.strftime("%Y-%m-%d %H:%M:%S", zifuchuan))
    
    输出:
    time.struct_time(tm_year=1974, tm_mon=9, tm_mday=18, tm_hour=21, tm_min=0, tm_sec=0, tm_wday=2, tm_yday=261, tm_isdst=0)
    1974-09-18 21:00:00
    

    2.datetime模块

    2.1将当期时间日期打印出来:

    print(datetime.datetime.now())
    
    输出:
    2017-02-22 22:00:57.059245
    

    2.2将时间戳直接转换为当前时间(详细时间,日期):

    print(datetime.datetime.fromtimestamp(time.time()))
    print(datetime.date.fromtimestamp(time.time()))
    
    输出:
    2017-02-22 22:04:39.177887
    2017-02-22
    

    2.3当前时间+3天,-3天,+3小时,-30分钟如下:

    print(datetime.datetime.now() + datetime.timedelta(3))
    print(datetime.datetime.now() + datetime.timedelta(-3))
    print(datetime.datetime.now() + datetime.timedelta(hours=3))
    print(datetime.datetime.now() + datetime.timedelta(minutes=-30))
    
    输出:
    2017-02-25 22:11:13.730289
    2017-02-19 22:11:13.730289
    2017-02-23 01:11:13.730289
    2017-02-22 22:41:13.730289
    

    2.4修改时间,将时间修改为2016-03-10:

    print(datetime.datetime.now().replace(2016, 3, 10))
    
    输出:
    2016-03-10 22:13:36.096497
    

    2.5获取前一天的时间:

    import datetime
    
    now_time = datetime.datetime.now()                          # 获取当前时间
    yes_time = now_time + datetime.timedelta(days=-1)           # 当前时间 -1
    yes_time_nyr = yes_time.strftime('%Y-%m-%d')                # 截取时间日期部分
    
    print(now_time)
    print(yes_time)
    print(yes_time_nyr)
    

    输出:

    2017-08-30 12:23:59.353665
    2017-08-29 12:23:59.353665
    2017-08-29
    

    3.random,string模块(生成随机字符串)

    3.1在区间数字之间随意抽取一个字符串:

    import random,string
    print(random.randint(1, 10))        # 会包括最大值 10
    print(random.randrange(1, 10))      # 不会包括最大值 10
    print(random.randrange(1, 100, 2))  # 取步长为2 奇数值 不包括100
    print(random.sample(range(100), 5))  # 随机取5个值
    
    输出:
    4
    1
    [68, 34, 42, 52, 11]
    

    3.2随机验证码:

    import random
    checkcode = ''
    for i in range(5):
        current = random.randrange(0, 5)
        if current != i:
            temp = chr(random.randint(65, 90))        # (65,90)为ASCII 中A-Z的大写字母
        else:
            temp = random.randint(0, 9)               # 从0-9 中间取一个数字
        checkcode += str(temp)                        # 将循环的字符串 拼接 输出
    print(checkcode)
    
    输出:
    H9J6H
    

    3.3生成字符列:

    import random,string
    
    print(string.ascii_uppercase)   # 大写字母
    print(string.ascii_lowercase)   # 小写字母
    print(string.ascii_letters)     # 大写字母+小写字母
    print(string.digits)            # 数字 0--9
    print(string.hexdigits)         # 数字 0--9 + a--f + A--F
    print(string.punctuation)       # 特殊字符
    print(string.printable)         # 数字0--9 + 小写 + 大写 + 特殊字符
    
    输出:
    ABCDEFGHIJKLMNOPQRSTUVWXYZ
    abcdefghijklmnopqrstuvwxyz
    abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ
    0123456789
    0123456789abcdefABCDEF
    !"#$%&'()*+,-./:;<=>?@[]^_`{|}~
    0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!"#$%&'()*+,-./:;<=>?@[]^_`{|}~
    

    3.4生成随机验证码二(将大小写字母+数字拼接在一起):

    import random,string
    abc = string.ascii_letters + string.digits + string.digits
    print("".join(random.sample(abc, 6)))
    

    4.OS模块

    导入模块:

    import os
    

    4.1获取当前用户的工作目录,相当于Linux下的pwd;os.getcwd()

    >>> import os
    >>> os.getcwd()
    '/root'
    

    4.2改变当前脚本的工作目录,相当于Linux下的cd;os.chdir("/var/log")

    >>> os.chdir("/var/log")
    >>> os.getcwd()         
    '/var/log'
    

    4.3运行shell命令;os.system("ls")

    os.system 只返回执行结果的状态,执行完成后就退出了
    >>> os.system("ls")
    bin  boot  dev  etc  home  lib  lib64  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var
    

    4.4创建联系多级目录;

    >>> os.makedirs("d1/d2/d3")
    >>> os.system("tree d1")
    d1
    └── d2
        └── d3
    

    4.4.1当目录存在时exist_ok=True不报错

    >>> os.makedirs("d1/d2/d3",exist_ok=True)
    

    4.5递归删除多个空目录d1/d2/d3 都会被删除,如果目录不为空报错

    >>> os.removedirs("d1/d2/d3")
    >>> os.system("tree d1")     
    d1 [error opening dir]
    0 directories, 0 files
    0
    

    4.6创建单个目录;

    >>> os.mkdir("test")
    >>> os.system("tree test")
    test
    

    4.7删除单个空目录;相当于linux中的rmdir 目录

    >>> os.rmdir("test")      
    

    4.8列出指定目录下一级所有文件和子目录

    >>> os.listdir(".")
    ['boot', 'dev', 'proc', 'run', 'sys', 'etc', 'root', 'tmp', 'var', 'usr', 'bin', 'sbin', 'lib', 'lib64', 'home', 'media', 'mnt', 'opt', 'srv', '.autorelabel', 'd1']
    

    4.9删除一个文件,不可以删除目录

    >>> os.remove("d1/d2/a")
    

    4.10重新命名 文件/目录

    >>> os.rename("d1","d1s")
    

    4.11获取文件的详细信息,创建时间、大小、访问修改时间等

    >>> os.stat("d1s")
    os.stat_result(st_mode=16877, st_ino=532527, st_dev=2051, st_nlink=3, st_uid=0, st_gid=0, st_size=34, st_atime=1487915706, st_mtime=1487915701, st_ctime=1487915721)
    

    4.11.1获取文件的大小

    >>> os.stat("d1s").st_size
    34
    

    4.12输出当前系统的路径分隔符“Linux”

    >>> os.sep
    '/'
    

    4.12.1输出当前系统的路径分隔符“windows”

    >>> os.sep
    '\'
    

    4.13输出当前平台的换行符“linux”

    >>> os.linesep
    '
    '
    

    4.13.1输出当前平台的换行符“windows”

    >>> os.linesep
    '
    '
    

    4.14输出分隔文件路径的分隔符

    >>> os.pathsep
    ':'
    

    4.15查看当前操作系统的平台platform模块

    >>> import platform
    >>> platform.platform()
    'Linux-3.10.0-327.36.2.el7.x86_64-x86_64-with-centos-7.2.1511-Core'
    # 简写
    >>> platform.system()  
    'Linux'
    

    4.16拿到命令的执行结果os.popen

    os.popen("df -h").read() 可以拿到命令的执行结果
    
    >>> a = os.popen("df -h").read()
    >>> print(a)
    文件系统        容量  已用  可用 已用% 挂载点
    /dev/sda3        48G   13G   36G   26% /
    devtmpfs        903M     0  903M    0% /dev
    tmpfs           912M     0  912M    0% /dev/shm
    tmpfs           912M   25M  888M    3% /run
    tmpfs           912M     0  912M    0% /sys/fs/cgroup
    /dev/sda1       197M  182M   15M   93% /boot
    tmpfs           183M     0  183M    0% /run/user/0
    

    4.17返回path规范化的绝对路径

    import os
    print(os.path.abspath(__file__))
    
    输出:
    C:UsersDpadPycharmProjectspy_s16day5OS模块os模块.py
    

    4.18将path分隔成目录和文件名的二元组返回

    file_path = os.path.abspath(__file__)
    print(os.path.split(file_path))
    
    输出:
    ('C:\Users\Dpad\PycharmProjects\py_s16\day5\OS模块', 'os模块.py')
    

    4.19将path路径的最后一层去除

    print(os.path.dirname(file_path))
    print(os.path.dirname(os.path.dirname(file_path)))
    
    输出:
    C:UsersDpadPycharmProjectspy_s16day5OS模块
    C:UsersDpadPycharmProjectspy_s16day5
    

    4.20返回path最后的文件名,如果path以/或结尾,那么返回空

    print(os.path.dirname(file_path))
    print(os.path.basename(os.path.dirname(file_path)))
    
    输出:
    C:UsersDpadPycharmProjectspy_s16day5OS模块
    OS模块
    

    4.21如果文件或目录存在,返回True否则返回False

    print(os.path.exists(path="os模块.py"))
    
    输出:
    True
    

    4.22如果path是绝对路径返回True

    print(os.path.isabs("C:/Users/Dpad/PycharmProjects/py_s16/day5/OS模块/os模块.py"))
    
    输出:
    True
    

    4.23如果path是一个文件返回True

    print(os.path.isfile(path="os模块.py"))
    
    输出:
    True
    

    4.24如果path是一个目录返回True

    print(os.path.isdir("C:/Users/Dpad/PycharmProjects/py_s16/day5/OS模块/"))
    
    输出:
    True
    

    4.25将多个路径拼接成一个路径

    print(os.path.join("c:\","a","b"))
    
    输出:
    c:a
    

    4.26返回path所指向文件或路径的最后存取时间,和最后修改时间(getatime、getmtime)

    print(os.path.getatime("C:/Users/Dpad/PycharmProjects/py_s16/day5/OS模块/"))
    print(os.path.getmtime("C:/Users/Dpad/PycharmProjects/py_s16/day5/OS模块/os模块.py"))
    
    输出:
    1487921722.556163
    1487921722.5354404
    

    4.27得到传入路径的所有子目录以及文件(由于是一个生成器所以需要使用next()取值)

    import os
    a = os.walk(r"C:Users")
    print(next(a))
    
    输出为一个3元素的元组:
    # 第一个:元素为 当前传入的目录
    # 第二个:元素为 当前传入目录下的所有子目录
    # 第三个:元素为 当前传入目录下的所有文件
    
    ('C:\Users', 
    ['All Users', 'Default', 'Default User', 'defaultuser0', 'Dpad', 'Public'],
     ['desktop.ini'])
    

    4.28取得一个目录下的所有子目录的详细路径

    import os
    def sepash(pash):
        a = os.walk(pash)
        for pathdir,_,files in a:
            # print(pathdir,files)
            for file in files:
                abspath = r"%s\%s" % (pathdir, file)             # 目录拼接操作
                print(abspath)
    
    sepash(r"C:UsersDpadPycharmProjectsPyS18day05a")
    

    输出:

    C:UsersDpadPycharmProjectsPyS18day05aa1.txt
    C:UsersDpadPycharmProjectsPyS18day05aa2.txt
    C:UsersDpadPycharmProjectsPyS18day05a11.txt
    C:UsersDpadPycharmProjectsPyS18day05a1c1c1.txt
    C:UsersDpadPycharmProjectsPyS18day05a22.txt
    

    4.29获取一个文件 a.mp4 的大小

    C:UsersDpadPycharmProjectsPyS1800作业02-FtpServer>dir
     驱动器 C 中的卷没有标签。
     卷的序列号是 F2CA-37BC
    
    C:UsersDpadPycharmProjectsPyS1800作业02-FtpServer 的目录
    2017/08/25  00:17    <DIR>          .
    2017/08/25  00:17    <DIR>          ..
    2017/08/19  17:59        88,960,348 a.mp4
    
    C:UsersDpadPycharmProjectsPyS1800作业02-FtpServer>python
    
    >>> import os
    >>> os.path.getsize("a.mp4")
    88960348
    

    5.sys模块

    1. 返回模块的搜索路径,初始化时使用PYTHONPATH环境变量的值

    import sys
    
    >>> sys.path
    ['', '/usr/local/lib/python35.zip', '/usr/local/lib/python3.5', '/usr/local/lib/python3.5/plat-linux', '/usr/local/lib/python3.5/lib-dynload', '/usr/local/lib/python3.5/site-packages']
    

    2. 过下标的方式获取用户输入的内容

    import sys
    print(sys.argv)
    

    输出:

    C:Usersadmin>python argv.py 1 2 3 4 5 6
    ['argv.py', '1', '2', '3', '4', '5', '6']
    

    3. copy一个不知存储方式的文件到别处
    cat copy.py

    import sys
    
    # print(sys.argv)
    if len(sys.argv) != 3:                                         # 判断用户给的参数个数
        print(""want 3 parameters"Usage: cp [OPTION]... SOURCE DEST")
        exit(1)
    
    with open(r"%s" % sys.argv[1],"rb") as ly_r, open(r"%s" % sys.argv[2],"wb") as ly_w:
        for i in ly_r:
            ly_w.write(i)
    

    4. sed替换文件内的指定内容
    cat sed.py

    import sys
    import os
    
    if len(sys.argv) != 4:                                         # 判断用户给的参数个数
        print(""want 4 parameters"Usage: sed.py old_file new_file file_name")
        exit(1)
    
    with open(sys.argv[3],"r",encoding="utf-8") as a_r, open("."+sys.argv[3]+"swp","w",encoding="utf-8") as b_w:
        for i in a_r:
            b = i.replace(sys.argv[1], sys.argv[2])                # 替换用户输入的参数
            b_w.write(b)
    
    os.remove(sys.argv[3])										   # 删除源文件
    os.rename("."+sys.argv[3]+"swp",sys.argv[3])				   # 将swp文件重新命名为 源文件
    

    6.json & pickle 模块

    用于序列化的两个模块
    1.json,用于字符串 和 python数据类型间进行转换
    2.pickle,用于python特有的类型 和 python的数据类型间进行转换
    Json模块提供了四个功能:dumps、dump、loads、load
    pickle模块提供了四个功能:dumps、dump、loads、load

    6.1事前案例(序列化和反序列化)

    1.将字典存入到文本中:(序列化)
    account = {
        "id": 622517715,
        "zonge": 15000,
        "yue": 8000,
        "guoqi": "2020-5-21",
        "password": "123123"
    }
    
    f = open("account.db", "w")
    
    f.write(str(account))   # 文本中存放只能是 bytes 和 字符串str
    f.close()
    

    2.在另一个文件中加载字典文件:(反序列化)

    f = open("account.db", "r")
    
    account = eval(f.read())        # 加载时将 字符串str 文件转换为 字典dict
    print(account)
    print(account["id"])            # 打印ID 索引
    
    输出:
    {'yue': 8000, 'id': 622517715, 'password': '123123', 'guoqi': '2020-5-21', 'zonge': 15000}
    622517715
    

    总结:
    1.序列化:内存---》字符串的转换
    2.反序列化:字符串---》内存

    6.2通过pickle的方式写入(不需要转换为字符串):(序列化pickle.dumps)

    import pickle
    account = {
        "id": 622517715,
        "zonge": 15000,
        "yue": 8000,
        "guoqi": "2020-5-21",
        "password": "123123"
    }
    
    f = open("account.db", "wb")    # pickle 默认依照bytes 格式存储所以 写入要已“wb” 格式
    # print(pickle.dumps(account))
    f.write(pickle.dumps(account))  # 等同于 pickle.dump(account, f)  将account 写入到 f 文件中
    
    f.close()
    

    6.3在另一个文件中加载序列化文件:(反序列化pickle.loads)

    import pickle
    
    f = open("account.db", "rb")        # pickle 默认依照bytes 格式存储所以 读取要已“rb” 格式
    account = pickle.loads(f.read())    # 等同于 account = pickle.load(f)  自动帮助read()
    print(account)
    
    print(account["id"])
    
    输出:
    {'password': '123123', 'id': 622517715, 'yue': 8000, 'guoqi': '2020-5-21', 'zonge': 15000}
    622517715
    

    6.4反序列化后,修改值在存入到文件中(反序列化--》修改--》序列化)

    import pickle
    
    f = open("account.db", "rb")
    account = pickle.loads(f.read())  # 等同于 account = pickle.load(f)  自动帮助read()
    print(account)
    print(account["id"])
    
    account["yue"] -= 3000
    f = open("account.db", "wb")
    f.write(pickle.dumps(account))    # 等同于 pickle.dump(account, f)  将account 写入到 f 文件中
    f.close()
    print(account)
    
    输出:
    {'password': '123123', 'id': 622517715, 'yue': 8000, 'guoqi': '2020-5-21', 'zonge': 15000}
    622517715
    {'password': '123123', 'id': 622517715, 'yue': 5000, 'guoqi': '2020-5-21', 'zonge': 15000}
    

    json模块

    pickle 和 json的区别
    1.json只支持 str,int,float,set,dict,list,tuple
    2.json跨平台通用的序列化的格式
    3.pickle 支持 Python中的所有格式;但是不能和其他平台语言通用;
    4.pickle 存储格式为bytes,所以写入和读取的时候 需要依照("wb" "rb")形式打开

    1.使用json实现序列化和反序列化,直接通过别名as

    import json as pickle
    account = {
        "id": 622517715,
        "zonge": 15000,
        "yue": 8000,
        "guoqi": "2020-5-21",
        "password": "123123"
    }
    
    # f = open("account.db", "wb")
    f = open("account.db", "w")
    f.write(pickle.dumps(account))   # 等同于  pickle.dump(account, f)
    f.close()
    

    2.反序列化将存入的数据读取出来:

    import json as pickle
    
    # f = open("account.db", "rb")
    f = open("account.db", "r")
    account = pickle.load(f)
    print(account)
    print(account["id"], account["yue"])
    f.close()
    
    输出:
    {'passwd': '123123', 'id': 376415700, 'balance': 8000, 'exp_date': '2019-5-20', 'credit': 15000}
    376415700 8000
    

    7.logging模块

    很多程序都有记录日志的需求,并且日志中包含的信息即有正常的程序访问日志,还可能有错误、警告等信息输出,python的logging模块提供了标准的日志接口,你可以通过它存储各种格式的日志,logging的日志可以分为 debug(), info(), warning(), error() and critical() 5个级别;

    7.1 日志模块的使用(输出屏幕):

    import logging
    
    logging.warning("user [bao] password more than 3 times")
    logging.critical("server is down")
    
    
    输出:
    WARNING:root:user [bao] password more than 3 times
    CRITICAL:root:server is down
    

    7.2 将日志写到文件中(basicConfig方法):

    import logging
    #语法:logging.basicConfig(filename="日志名称", level=logging.级别达到级别就写入)
    
    logging.basicConfig(filename="example.log", level=logging.INFO)
    
    logging.debug('This message should go to the log file')   # 由于是INFO 级别所以debug日志内容不会写入到 文件中
    logging.warning("user [bao] password more than 3 times")
    logging.critical("server is down")
    logging.info('So should this')
    
    example.log文件内容:
    WARNING:root:user [bao] password more than 3 times
    CRITICAL:root:server is down
    INFO:root:So should this
    

    7.3 将日志输出是加上时间:

    import logging
    
    logging.basicConfig(filename="example.log",
                        level=logging.DEBUG,
                        format='%(asctime)s %(message)s',       # asctime 当前时间  message 日志内容
                        datefmt='%Y/%m/%d %H:%M:%S %p'          # 日期格式
                        )
    
    logging.debug('This message should go to the log file')
    logging.warning("user [bao] password more than 3 times")
    logging.critical("server is down")
    logging.info('So should this')
    
    
    example.log文件内容:
    2017/02/23 18:34:07 PM This message should go to the log file
    2017/02/23 18:34:07 PM user [bao] password more than 3 times
    2017/02/23 18:34:07 PM server is down
    2017/02/23 18:34:07 PM So should this
    

    7.4 将日志按照需求的模块打印(asctime 当前时间 process 进程ID filename 文件的名字 funcName 函数的名字 lineno 打印的哪一行 message 日志内容)

    import logging
    
    logging.basicConfig(filename="example.log",
                        level=logging.DEBUG,
                        format='%(asctime)s pid:%(process)d %(filename)s:%(funcName)s:%(lineno)d %(message)s', 
                        # asctime 当前时间  process 进程ID  filename 文件的名字 funcName 函数的名字 lineno 打印的哪一行  message 日志内容
                        datefmt='%Y/%m/%d %H:%M:%S %p'          # 日期格式
                        )
    
    def sayhi():
        logging.info('print logging in sayhi')
    
    logging.debug('This message should go to the log file')
    logging.warning("user [bao] password more than 3 times")
    logging.critical("server is down")
    logging.info('So should this')
    
    sayhi()
    
    
    example.log文件内容:
    2017/02/23 18:54:36 PM pid:19552 loggings模块.py:<module>:17 This message should go to the log file
    2017/02/23 18:54:36 PM pid:19552 loggings模块.py:<module>:18 user [bao] password more than 3 times
    2017/02/23 18:54:36 PM pid:19552 loggings模块.py:<module>:19 server is down
    2017/02/23 18:54:36 PM pid:19552 loggings模块.py:<module>:20 So should this
    2017/02/23 18:54:36 PM pid:19552 loggings模块.py:sayhi:15 print logging in sayhi
    

    7.5日志(按照:大小、时间)截断:
    Python 使用logging模块记录日志涉及四个主要类:

    1. logger提供了应用程序可以直接使用的接口;
    2. handler将(logger创建的)日志记录发送到合适的目的输出(屏幕、文件);
    3. filter提供了细度设备来决定输出哪条日志记录(过滤筛选);
    4. formatter决定日志记录的最终输出格式。
      调用关系(如图):
      logger接口
    # 导入日志模块,导入日志切割模块
    import logging
    from logging import handlers
    
    # 定义logger 接口
    logger = logging.getLogger('TEST-LOG')  # 向公共日志里打 文件时用于日志区分
    logger.setLevel(logging.DEBUG)          # 全局日志 级别(DEBUG)
    
    # 屏幕handler 输出 ch
    ch = logging.StreamHandler()            # 屏幕 Handler 赋值给ch
    ch.setLevel(logging.INFO)               # 屏幕 输出日志级别(INFO)
    
    # 文件handler 记录到文件中 日志 fh
    # fh = logging.FileHandler("access.log")  # 记录到access.log 文件中 赋值给 fh
    fh = handlers.TimedRotatingFileHandler("access.log", when="h", interval=24, backupCount=7) 
    # 记录到文件中,每间隔24小时切割一份日志,一共保留7份超出的部分自动删除
    # fh = handlers.RotatingFileHandler("access.log", maxBytes=4, backupCount=7)  # 记录到文件中,当日志满4b后切割,保留7份
    fh.setLevel(logging.INFO)            # 记录到文件中 日志 级别(INFO)
    
    # 写日志格式  时间---名字(TEST-LOG)---文本形式的日志级别---日志内容
    formatter = logging.Formatter('%(asctime)s pid:%(process)d %(filename)s:%(funcName)s:%(lineno)d %(message)s')
    
    # 将屏幕输出 handler 和 日志格式绑定起来 formatter ch
    # 将文件输出 handler 和 日志格式绑定起来 formatter fh
    ch.setFormatter(formatter)
    fh.setFormatter(formatter)
    
    # 日志接口 也要和 屏幕输出 handler 绑定 ch
    # 日志接口 也要和 文件输出 handler 绑定 fh
    logger.addHandler(ch)
    logger.addHandler(fh)
    
    # 'application' code
    logger.debug('debug message')
    logger.info('info message')
    logger.warn('warn message')
    logger.error('error message')
    logger.critical('critical message')
    logger.info('info message')
    
    输出:
    2017-02-24 11:30:41,039 pid:18580 loggings模块.py:<module>:64 info message
    2017-02-24 11:30:41,039 pid:18580 loggings模块.py:<module>:65 warn message
    2017-02-24 11:30:41,039 pid:18580 loggings模块.py:<module>:66 error message
    2017-02-24 11:30:41,039 pid:18580 loggings模块.py:<module>:67 critical message
    2017-02-24 11:30:41,039 pid:18580 loggings模块.py:<module>:68 info message
    

    8.hashlib模块

    hash:是一种算法,Python3.x里代替了md5模块和sha模块,主要提供SHA1,SHA224, SHA256, SHA384, SHA512 ,MD5 算法

    8.1hash的特点

    1. 内容相同则hash运算结果相同,内容稍微改变则hash值则变
    2. 不可逆推
    3. 相同算法,无论效验多长的数据,得到的哈希值长度固定
    4. hash校验的数据类型需要时bytes类型

    8.2语法

    1 . 分批次传值,可以达到一样的效果

    import hashlib
    
    m=hashlib.md5()
    m.update('hello'.encode('utf-8'))       # 可以分批次传值
    m.update('world'.encode('utf-8'))       # 继续传值
    print(m.hexdigest())
    

    输出

    fc5e038d38a57032085441e7fe7010b0
    

    2 . 将值一次update过去,可以发现hash值是相同的

    m=hashlib.md5()
    m.update('helloworld'.encode('utf-8'))
    print(m.hexdigest())
    

    输出

    fc5e038d38a57032085441e7fe7010b0
    

    3 . 效验一个文本的内容是否完整

    # 推荐使用一行行的效验
    m = hashlib.md5()
    with open("a.xml","rb") as f:
        for line in f:
            m.update(line)
    print(m.hexdigest())
    
    # 不推荐使用全部加载(耗资源)
    m = hashlib.md5()
    with open("a.xml","rb") as f:
        m.update(f.read())
    print(m.hexdigest())
    

    输出:

    41bbdc6e6eee194233645e72f83594cd
    41bbdc6e6eee194233645e72f83594cd
    

    4 . 除了md5模式的效验,还可以使用SHA1,SHA224, SHA256, SHA384, SHA512算法,使用方法相同

    # 推荐使用一行行的效验
    m = hashlib.sha512()
    with open("a.xml","rb") as f:
        for line in f:
            m.update(line)
    print(m.hexdigest())
    
    # 不推荐使用全部加载(耗资源)
    m = hashlib.sha512()
    with open("a.xml","rb") as f:
        m.update(f.read())
    
    print(m.hexdigest())
    

    输出:

    bfd023774d6a7fafcf368afa8894e534e44995abeb6509c6988088e7a04af9dfb50caaf67e3259e9ad5bc53a36882798d0b3801e76f2a103f6ee609289a3774a
    bfd023774d6a7fafcf368afa8894e534e44995abeb6509c6988088e7a04af9dfb50caaf67e3259e9ad5bc53a36882798d0b3801e76f2a103f6ee609289a3774a
    

    8.3hmac模块(加盐)

    hmac模块它内部对我们创建key和内容进行进一步的处理然后加密

    #要想保证hmac最终结果一致,必须保证:
    #1:hmac.new括号内指定的初始key一样
    #2:无论update多少次,校验的内容累加到一起是一样的内容
    
    import hmac
    
    h1=hmac.new(b'lin')        # 需要保证 hmac.new 的值为相同
    h1.update(b'hello')        # update值和md5形式一样,可以多次update
    h1.update(b'world')
    print(h1.hexdigest())
    
    h2=hmac.new(b'lin')        # 需要保证 hmac.new 的值为相同
    h2.update(b'helloworld')
    print(h2.hexdigest())
    

    输出结果:

    c10bd498bd6e7dbc5dd5c3fb3396a165
    c10bd498bd6e7dbc5dd5c3fb3396a165
    

    9.suprocess模块(可用于执行系统命令,将返回值输出到stdout、stderr)

    1 . 用于执行系命令,默认将返回值直接输出到终端,可以指定输出到stdout、stderr

    import subprocess
    
    res = subprocess.Popen(r"dir C:UsersDpadPycharmProjectsPython07",     # 一条可执行的命令
                           shell=True,                                          # 标准格式
                           stdout=subprocess.PIPE,                              # 将正确内容指向到stdout管道中
                           stderr=subprocess.PIPE,)                             # 将错误内容指向到stdout管道中
                           
    print("正确输出:", res.stdout.read().decode("gbk"))        # 命令正确时,内容会放在stdout内部
    print("错误输出:", res.stderr.read().decode("gbk"))        # 命令执行错误时,内容会放在stderr内部
    

    输出(发现错误输出内容为空):

    正确输出:  驱动器 C 中的卷没有标签。
     卷的序列号是 F2xA-37zC
    
     C:UsersDpadPycharmProjectsPython07 的目录
    
    2017/08/15  00:35    <DIR>          .
    2017/08/15  00:35    <DIR>          ..
    2017/08/15  00:36    <DIR>          hashblib模块
    2017/08/15  00:53    <DIR>          subprocess模块
    2017/08/12  10:45    <DIR>          xml模块
    2017/08/12  18:11    <DIR>          面向对象
                   0 个文件              0 字节
                   6 个目录 168,254,607,360 可用字节
    
    错误输出: 
    

    2 . 将得到的输出结果,通过stdin形式传入给另一个条件,实现管道查询

    import subprocess
    res1 = subprocess.Popen(r"dir C:UsersDpadVPN-FanX",   # 查看该目录下的内容
                            shell=True,
                            stdout=subprocess.PIPE,)         # 输出到stdout
    
    res2 = subprocess.Popen(r"findstr exe$",                 # findstr查找依照 exe结尾的文件
                            shell=True,    
                            stdin=res1.stdout,               # 输入来源res1.stdout
                            stdout=subprocess.PIPE,)         # 结果输出到stdout
    
    print("依照exe结尾的文件有:
    ",res2.stdout.read().decode("gbk"))            # 打印查找到的结果
    

    输出:

    依照exe结尾的文件有:
     2015/08/04  01:41           305,664 Shadowsocks.exe
    2013/05/27  10:46         2,617,344 ssocks32.exe
    2013/05/27  10:46         3,225,600 ssocks64.exe
    2013/06/05  12:55           952,320 yingwa.exe
    
  • 相关阅读:
    20199307 2019-2020-2 《网络攻防实践》第二周作业
    20199307 2019-2020-2 《网络攻防实践》第一周作业
    20199307 《网络攻防实践》假期作业
    缓冲区溢出漏洞实验
    2019-2020-1 20199307《Linux内核原理与分析》第十二周作业
    2019-2020-1 20199307《Linux内核原理与分析》第十一周作业
    第二周测试-myod(选做)
    2019-2020-1 20199307《Linux内核原理与分析》第九周作业
    20199306 2019-2020-2 《网络攻防实践》第3周作业
    20199306 2019-2020-2 《网络攻防实践》第2周作业
  • 原文地址:https://www.cnblogs.com/baolin2200/p/6406414.html
Copyright © 2020-2023  润新知