主頁 > 後端開發 > 17_Python的常用模塊

17_Python的常用模塊

2020-09-15 18:54:35 後端開發

1.亂數模塊 random

    1.隨機小數

import random

# (0,1)隨機取浮點數
random.random()  # 0.17988578778011

# (1, 3)取指定范圍的浮點數
random.uniform(1,3)  # 2.3793286185319555

    2.隨機整數

import random

# [1, 3]隨機取整數
random.randint(1, 3)  # 1

# [1, 3)隨機取整數
random.randrange(1, 3)  # 1

    3.隨機選擇回傳一個和隨機選擇回傳多個

import random

# [可迭代序列]取隨機值
random.choice([11, 22, 33])  # 22

# [可迭代序列]取隨機2個值,回傳的個數為函式的第二個引數
random.sample([11, 22, 33], 2)  # [11, 22]

    4.打亂串列序列

import random

# 隨機打亂串列的序列
item = [1, 2, 3, 4, 5]
random.shuffle(item)
print(item)  # [2, 1, 4, 5, 3]

    5.其他方法

import random

# 以長整型的形式回傳用nbit位來表示的亂數
random.getrandbits(nbit)
# 生成一個16位元長的隨機整數
random.getrandbits(16)  # 20962

# 用給定的數a設定隨機種子,不給引數a則用當前時間設定隨機種子
random.seed(a=None)

# 亂數產生與種子有關,如果種子是1,第一個數必定是這個
random.seed(1)  # 產生種子1對應的序列
print(random.random())  # 0.13436424411240122
print(random.random())  # 0.8474337369372327

random.seed(1)  # 產生種子1對應的序列
print(random.random())  # 0.13436424411240122
print(random.random())  # 0.8474337369372327

    6.生成指定長度的隨機驗證碼

import random


def v_code(num):
    code = ""
    for i in range(num):
        num = random.randint(0, 9)
        # alf = chr(random.randint(65, 90))
        alf = chr(random.choice([random.randint(65, 90),random.randint(97, 122)]))
        add = random.choice([num, alf])
        code = "".join([code, str(add)])
    return code


print(v_code(6))

2.與系統相關模塊 os

    1.os模塊概述
        os模塊是與作業系統互動的一個介面
        匯入語法: import os

    2.檔案操作

import os

# remove 洗掉一個檔案
os.remove("test1/111")  # 洗掉指定路徑的檔案,如果指定的路徑是一個目錄,將拋出例外FileNotFoundError
os.unlink("a.txt")  # 洗掉檔案,如果檔案是一個目錄,將拋出例外FileNotFoundError

# 遞回洗掉目錄和檔案夾
for root, dirs, files in os.walk(top, topdown=False):
    for name in files:
        os.remove(os.path.join(root, name))
    for name in dirs:
        os.rmdir(os.path.join(root, name))

# 遞回遍歷目錄和檔案個數
    # dir_count: 不僅會統計一級子檔案夾還會統計二級三級子檔案夾依次類推一級子檔案夾若有一個子檔案夾會記作兩個
    dir_count = 0
    # file_count: 不僅會統計檔案夾下的檔案,還會統計子檔案夾下的檔案
    file_count = 0
    for root, dirs, filenames in os.walk(file_path):
        for dir in dirs:
            dir_count += 1
        for file in filenames:
            file_count += 1
    print("dir_count", dir_count)
    print("file_count", file_count)

# rename 重命名檔案/目錄
os.rename("test1", "test1")

    3.目錄操作

import os

# getcwd獲取當前作業目錄,即當前python腳本作業目錄路徑
print(os.getcwd())  # G:\PycharmProjects\11_模塊\lnh_massage

# chdir改變當前腳本的作業目錄,相當于shell下的cd命令
os.chdir("test1")
print(os.getcwd())  # G:\PycharmProjects\11_模塊\lnh_massage\test1
os.chdir("..")
print(os.getcwd())  # G:\PycharmProjects\11_模塊\lnh_massage

# curdir回傳當前目錄
print(os.curdir)  # .

# pardir獲取當前父目錄字串名
print(os.pardir)  # ..

# makedirs 可遞回創建檔案夾
os.makedirs("makir1/mkdir2")

# removedirs 檔案夾為空則可遞回洗掉檔案夾,知道非空為止
os.removedirs("makir1/mkdir2")

# mkdir 生成單級目錄
os.mkdir("test2")

# rmdir 洗掉單級空目錄,目錄不為空則無法洗掉
os.rmdir("test2")

# listdir 列出指定檔案下的所有檔案和子目錄,包含影藏檔案,回傳一個串列
print(os.listdir("test1"))

# stat 獲取檔案/目錄資訊
print(os.stat(r"G:\PycharmProjects\11_模塊\lnh_massage"))
"""stat結構
    st_mode: inode 保護模式
    st_ino: inode 節點號
    st_dev: inode 駐留的設備
    st_nlink: inode 的鏈接數
    st_uid: 所有者的用戶ID
    st_gid: 所有者的組ID
    st_size: 普通檔案以位元組為單位的大小,包含等待某些特殊檔案的資料
    st_atime: 上次訪問的時間
    st_mtime: 最后一次修改的時間
    st_ctime: 由作業系統報告的"ctime",在某些系統上(如Unix)是最新的元資料更改的時間在其它系統上(如Windows)是創建時間
"""

    4.系統相關操作

import os

# sep 查看作業系統的特定路徑分割符
print(os.sep)  # Windows為: "\",Linux為: "/"

# linesep 查看當前平臺使用的終止符
print("終止符", os.linesep)  # win下"\r\n",linux下"\n"

# pathsep 查看用于分割檔案路徑的字串
print("分隔檔案", os.pathsep)  # win下",",linux下":"

# name 以字串指示查看當前使用平臺
print("使用平臺", os.name)  # win下"nt",linux下"posix"

# system 用于運行shell命令
os.system("ping 127.0.0.1")

# popen 運行系統命令并回傳執行結果,win平臺: dir Linux平臺: ls, pwd等
r = os.popen("pwd") 
print(r.read())  # /Users/tangxuecheng

# urandom 回傳一個指定長度的bytes型別資料
b = os.urandom(5)
print(b)  # b'\xbc\xd9\xbc\xb0\xb8'

    5.path相關操作

import os

# environ 獲取系統環境變數
print(os.environ)

# path.abspath() 回傳規范化的path絕對路徑
print(os.path.abspath(r"G:\PycharmProjects\11_模塊\lnh_massage\test1"))
# G:\PycharmProjects\11_模塊\lnh_massage\test1

# path.split 將path分割成目錄和檔案名,回傳元組
print(os.path.split(r"G:\PycharmProjects\11_模塊\lnh_massage\test1"))
# ('G:\\PycharmProjects\\11_模塊\\lnh_massage', 'test1')

# path.dirname 回傳path.split的第一個元素,目錄
print(os.path.dirname(r"G:\PycharmProjects\11_模塊\lnh_massage\test1"))
# G:\PycharmProjects\11_模塊\lnh_massage

# basename 回傳path.split的第二個元素,檔案名
print(os.path.basename(r"G:\PycharmProjects\11_模塊\lnh_massage\test1"))  # test1

# path.exists 判斷path是否存在,回傳布林值
print(os.path.exists(r"G:\PycharmProjects\11_模塊\lnh_massage\test1"))  # True

# path.isabs 判斷path是否是絕對路徑,回傳布林值
print(os.path.isabs(r"G:\PycharmProjects\11_模塊\lnh_massage\test1"))  # True

# path.isfile 判斷path是否是一個存在的檔案,回傳布林值
print(os.path.isfile(r"G:\PycharmProjects\11_模塊\lnh_massage\test1"))  # False

# path.isdir 判斷path是否是一個存在的目錄
print(os.path.isdir(r"G:\PycharmProjects\11_模塊\lnh_massage\test1"))  # True

# path.join 路徑拼接,會自動去找當前作業系統的路徑分割符拼接
a = r"G:\PycharmProjects"
b = r"11_模塊\lnh_massage\test1"
print(os.path.join(a, b))  # G:\PycharmProjects\11_模塊\lnh_massage\test1

# path.getatime 回傳path所指向的檔案或目錄最后一次存取時間
print(os.path.getatime(r"G:\PycharmProjects\11_模塊\lnh_massage\test1"))
# 1553962262.1905563

# path.getmtime 回傳path所指向的檔案或目錄最后一次修改時間
print(os.path.getmtime(r"G:\PycharmProjects\11_模塊\lnh_massage\test1"))
# 1553962262.1905563

# path.getsize 回傳path所指向的檔案的大小,單位為位元組
print(os.path.getsize(r"G:\PycharmProjects\11_模塊\lnh_massage\test1"))  # 397

    6.行程相關

import os

# 創建一個新的行程,回傳的pid為新的行程的PID
pid = os.fork()

# 獲取當前行程的PID號
print(os.getpid())  # 10181

# 獲取當前行程父行程的PID號
print(os.getppid())  # 10148

# 結束行程,引數是一個整數表示行程的結束狀態
print(os._exit(1))

# 等待子行程退出進行處理
p, status = os.wait()  # 回傳值: 一個二元元組,第一個值為退出的子行程PID,第二個值為子行程退出狀態
os.WEXITSTATUS(status)  # 獲取結束狀態原數

3.與解釋器相關模塊 sys

    1.sys模塊概述
        sys模塊是與python解釋器互動的一個介面
        匯入語法: import sys

    2.變數

import sys

# 模塊搜索路徑 path[0] 是當前腳本程式的路徑名,否則為 ''
sys.path
"""執行結果
    ['D:\\Program Files (x86)\\Scripts\\ipython.exe',
     'd:\\program files (x86)\\python37.zip',
     'd:\\program files (x86)\\DLLs',
     'd:\\program files (x86)\\lib',
     'd:\\program files (x86)',
     '',
     'd:\\program files (x86)\\lib\\site-packages',
     'd:\\program files (x86)\\lib\\site-packages\\IPython\\extensions',
     'C:\\Users\\Administrator\\.ipython']
"""

# 已加載模塊的字典
sys.modules

# 版本資訊字串
sys.version  # '3.7.7 (default, Mar 10 2020, 15:43:33) \n[Clang 11.0.0 (clang-1100.0.33.17)]'


# 版本資訊的命名元組
sys.version_info  # sys.version_info(major=3, minor=7, micro=7, releaselevel='final', serial=0)


# 作業系統平臺名稱資訊
sys.platform  # 'darwin'

# 命令列引數 argv[0] 代表當前腳本程式路徑名
sys.argv  # ['/usr/local/bin/ipython']

# 獲得Python著作權相關的資訊
sys.copyright

# 獲得Python內建模塊的名稱(字串元組)
sys.builtin_module_names

    3.標準輸入輸出

import sys

# 標準輸入檔案物件,多用于input()
sys.stdin
s = sys.stdin.read(10)  # 默認從鍵盤獲取
print(s)

# 標準輸出檔案物件,多用于print()
sys.stdout
s = sys.stdout.write("hello world!\n")  # hello world!
print(s)  # 13

# 標準錯誤輸出檔案物件,用于輸出錯誤資訊
sys.stderr
s =  sys.stderr.write("錯誤資訊輸出\n")  # 錯誤資訊輸出
print(s)  # 7

# 查看 標準輸入/輸出/錯誤輸出 的檔案描述符
print(sys.stdin.fileno())  # 0
print(sys.stdout.fileno())  # 1
print(sys.stderr.fileno())  # 2

    4.方法

import sys

# 結束一個行程并拋出例外,傳入一個正整數表示結束狀態
sys.exit()  # 不寫引數默認為0正常結束

# 傳入字串表示列印行程結束語 sys.exit("end")
sys.exit("end")

# 得到遞回嵌套層次限制(堆疊的深度)
sys.getrecursionlimit()  # 3000

# 得到和修改遞回嵌套層次限制(堆疊的深度)
sys.setrecursionlimit(n)

# 指定字串加入小資料池
a = sys.intern('hello!@'*20)
b = sys.intern('hello!@'*20)
print(a is b)  # True

# 獲取檔案名: 獲取當前位置所在的檔案名
print(sys._getframe().f_code.co_filename)  # <ipython-input-10-dfaee55b6107>

# 獲取函式名: 獲取當前位置所在的函式名
print(sys._getframe().f_code.co_name)  # <module>

# 獲取行號: 當前位置所在的行號
print(sys._getframe().f_lineno)  # 1

    5.進度條示例

import sys
import time

for i in range(100):
    sys.stdout.write("#")  # 向螢屏顯示相應的內容
    time.sleep(0.1)
    sys.stdout.flush()  # 重繪快取

    6.例外處理和status

import sys

try:
    sys.exit(1)
except SystemExit as e:
    print(e)

4.正則模塊 re

    1.正則運算式概述

        1.正則運算式就是匹配字串內容的一種規則

        2.模塊匯入語法: import re

        3.元字符

            . 匹配除換行符以外的任意字符
            \w 匹配字母或數字或下劃線
            \s 匹配任意的空白符
            \d 匹配數字
            \n 匹配一個換行符
            \t 匹配一個制表符
            \b 匹配一個單詞的結尾
            ^ 匹配字串的開始
            $ 匹配字串的結尾
            \W 匹配非字母或數字或下劃線
            \D 匹配非數字
            \S 匹配非空白符
            a|b 匹配字符a或字符b
            () 匹配括號內的運算式,也表示一個組
            [...] 匹配字符組中的字符
            [^...] 匹配除了字符組中字符的所有字符

        4.量詞

            * 重復零次或更多次
            + 重復一次或更多次
            ? 重復零次或一次
            {n} 重復n次
            {n,} 重復n次或更多次
            {n,m} 重復n到m次

        5.貪婪和非貪婪

            .* 默認為貪婪匹配模式,會匹配盡量長的字串
            .*? 加上?為將貪婪匹配模式轉為非貪婪匹配模式,會匹配盡量短的字串
            常用示例:
                *? 重復任意次,但盡可能少重復
                +? 重復1次或更多次,但盡可能少重復
                ?? 重復0次或1次,但盡可能少重復
                {n,m}? 重復n到m次,但盡可能少重復
                {n,}? 重復n次以上,但盡可能少重復

        6.分組

            () 可以為正則運算式建立一個子組,子組可以看做內部的整體
            子組的概述:
                1.子組可以改變重復元字符的重復行為,增加子組后對正則運算式整體的匹配內容沒有影響
                2.子組在某些操作中可以對子組匹配內容單獨提取,子組通常不要交叉使用
                3.每個正則運算式可以有多個子組,由外到內由左到右依次為第一子組,第二子組
            捕獲組和非捕獲組(命名組和非命名組)
                1.子組命名格式: (?Pabc)
                2.很多編程介面可以直接通過名字獲取子組的匹配內容
                3.捕獲組中的正則運算式可以通過名字重復呼叫: (?P=name)

In [43]: import re

In [44]: re.search("(ab)+", "ababababab").group()
Out[44]: 'ababababab'

In [45]: re.search("(?P<dog>ab)cdef(?P=dog)", "abcdefabcde").group()
Out[45]: 'abcdefab'

    2.普通字符

import re

# 匹配相應的普通字符
print(re.findall("coco", "my name is coco hao are you"))  # ['coco']

    3.元字符: . ^ $ [] | () \

import re

# .匹配除了\n以外的所有字符,一個點代指1個字符
print(re.findall("m.....e", "my name is coco hao are you"))  # ['my name']

# .匹配包括\n的所有字符,需要傳入第三個引數re.S
print(re.findall(".*", "hello\nworld!"))  # ['hello', '', 'world!', '']
print(re.findall(".*", "hello\nworld!", re.S))  # ['hello\nworld!', '']
print(re.search(".*", "hello\nworld!").group())  # hello
print(re.search(".*", "hello\nworld!", re.S).group())
"""
    hello
    world!
"""

# ^只能在字串開頭匹配內容,表示匹配一個字串的開始位置
print(re.findall("^m..n", "my name is coco hao are you"))  # ['my n']

# $只能在字串結尾匹配內容,表示匹配一個字串的結尾位置
print(re.findall("e...u$", "my name is coco hao are you"))  # ['e you']

# []字符集,匹配括號范圍內的任意一個字符,字符集里的功能符號只有- ^ \
print(re.findall("x[yz]", "xyaaaxz"))  # ['xy', 'xz']
# -范圍
print(re.findall("x[a-z]", "xyappxcappxzapp"))  # ['xy', 'xc', 'xz']
# ^非
print(re.findall("x[^a-z]", "xyappxcappxzappx1"))  # ['x1']

# |管道符-->或,匹配兩邊任意一個正則運算式符合條件的情況
print(re.findall("ac|b", "123ac566546b"))  # ['ac', 'b']
print(re.search(r"^[a-z]{2,8}@(139|163)\.com$", "[email protected]").group(1))  # 139
print(re.match(r"[a-z]{2,8}@(139|163)\.com$", "[email protected]").group(1))  # 163

# ()分組,使用括號可以為正則運算式建立一個子組,子組可以看做內部的整體
print(re.findall("(abc)+", "abc11abc22abc33"))  # ['abc', 'abc', 'abc']
# search 如果search中有分組的話,通過group(n)就能夠拿到group中的匹配的內容
# \1表示和第一個分組中的值相同
print(re.search(r"<(\w*)>(.*)</\1>", "<h1>[email protected]</h1>").group(2))  # [email protected]

# (?P<name>正則運算式) 表示給分組起別名,(?P=name) 表示參考別名為分組匹配到的字串
ret = re.search("(?P<name>[a-z]+)(?P<age>\d+)","coco26echo30").group("name")
print(ret)  # coco
ret = re.search(r"<(?P<h>\w*)>(.*)</(?P=h)>", "<h1>[email protected]</h1>").group("h")
print(ret)  # h1

# ?:取消分組優先顯示
ret= re.findall("www\.(baidu|163)\.com", "aawww.baidu.combb")
print(ret)  # ['baidu']
ret= re.findall("www\.(?:baidu|163)\.com", "aawww.baidu.combb")
print(ret)  # ['www.baidu.com']

# \轉義元字符
print(re.findall("5\*3\+2", "5*3+2-10"))  # ['5*3+2']
# \d: 匹配任意十進制數,相當于[0-9]
print(re.findall("\d+", "1+(2*3+5-(2-(5-4)))"))  # ['1', '2', '3', '5', '2', '5', '4']
# \D: 匹配任意非十進制數,相當于[^0-9]
print(re.findall("\D+", "1+(2*3+5-(2-(5-4)))"))  # ['+(', '*', '+', '-(', '-(', '-', ')))']
# \s: 匹配任何空白字符,相當于[\n\t\r\f\v]
print(re.findall("\s+", "hello world"))  # [' ']
# \S: 匹配任何非空白字符,相當于[^\n\t\r\f\v]
print(re.findall("\S+", "hello world"))  # ['hello', 'world']
# \w: 匹配任何字母數字,相當于[a-zA-z0-9_]
print(re.findall("\w+", "hello world 12345"))  # ['hello', 'world', '12345']
# \W: 匹配任何非字母數字,相當于[^a-zA-z0-9_]
print(re.findall("\W+", "hello world 12345"))  # [' ', ' ']
# \b: 匹配一個特殊字符邊界,如空格 & # 等,r原生字串:r后面的字串pythonIDE不解釋,交給re解釋
print(re.findall(r"lo\b", "hello hello#hello&"))  # ['lo', 'lo', 'lo']
# \B: 匹配一個特殊字符非邊界,如非空格 非& 非# 等,r原生字串:r后面的字串pythonIDE不解釋,交給re解釋
print(re.findall(r"el\B", "hello hello#hello&"))  # ['el', 'el', 'el']
# \A: 匹配開始位置,相當于^
print(re.findall("\A\w+", "hello world 12345"))  # ['hello']
# \Z: 匹配結束位置,相當于$
print(re.findall("\d+\Z", "hello world 12345"))  # ['12345']
# \A...\Z: 絕對匹配,以什么開始以什么結束,相當于 ^...$
print(re.findall("\A/\w+/\w+\Z", "/Users/tangxuecheng"))  # ['/Users/tangxuecheng']

    4.量詞: * + ? {}

# *匹配0-無窮次前面的內容
print(re.findall("^d*", "dddddefghddd"))  # ['ddddd']

# +匹配1-無窮次的內容
print(re.findall("d+", "dddddefghddd"))  # ['ddddd', 'ddd']

# ?匹配0次或者1次的內容
print(re.findall("ghf?", "dddddefghddd"))  # ['gh']

# {n}匹配指定重重復n次的內容
print(re.findall("ghd{3}", "dddddefghddd"))  # ['ghddd']
# {m,n}匹配指定重復m次到n次的內容
print(re.findall("ghd{0,2}", "dddddefghddd"))  # ['ghdd']

    5.查找方法: findall, search, match, fullmatch

# findall(pattern, string, flags=0)查找方法: 回傳一個串列值為所有匹配上的項
# findall會優先顯示分組中的內容,要想取消分組優先(?:正則運算式)
ret = re.findall('\d+', '19874ashfk01248')
print(ret)  # ['19874', '01248']
ret1 = re.findall('\s+', '19874ashfk01248')
print(ret1)  # []

# search(pattern, string, flags)查找方法: 匹配一個字串,匹配到回傳math物件,沒有匹配到回傳None
ret = re.search('\d+', '@$19874ashfk01248')
print(ret)  # <re.Match object; span=(2, 7), match='19874'>
# 回傳的物件通過group來獲取匹配到的第一個結果
if ret:
    print(ret.group())  # 19874
ret = re.search('\s+', '19874ashfk01248')  # 回傳值型別: None 如果沒有匹配上就是None
print(ret)  # None

# mach(pattern, string, flags)查找方法: 匹配一個字串的開頭位置,匹配到回傳math物件,沒有匹配到回傳None
ret = re.match('\d+', '19874ashfk01248')  # 同search用法,不同在以字串開始出進行匹配
print(ret)  # <re.Match object; span=(0, 5), match='19874'>
ret = re.match("a", "abc").group()
print(ret)  # a

# fullmatch(pattern, string, flags)查找方法: 要求目標字串完全匹配
ret = re.fullmatch("\w+", "abc123")
print(ret.group())  # abc123

    6.分割和替換方法: split, sub, subn

# split(pattern, string, flags): 按照正則運算式分割字串方法,遇到分組會保留分組內被切掉的內容
ret = re.split("[ab]", "abcd")  # 先按a分割得""和"bcd"再對""和"bcd"按b分割
print(ret)  # ['', '', 'cd']

# sub(pattern, replaceStr, string, max, flags): 替換正則運算式匹配到的內容方法,回傳替換后的字串
# 引數一正則運算式,引數二要替換的內容,引數三目標字串,引數四最多替換幾處,引數五為功能標志位
ret = re.sub("\d+", "A", "d22d33sd44", 2)
print(ret)  # dAdAsd44

# subn(pattern, repl, string, count, flags): 替換正則運算式匹配到的內容方法,回傳替換后的字串和實際替換的個數
# 引數一正則運算式,引數二要替換的內容,引數三目標字串,引數四最多替換幾處,引數五為功能標志位
ret = re.subn("\d+", "A", "d22d33sd44")
print(ret)  # ('dAdAsdA', 3)

    7.爬蟲效率方法: compile
        概述: compile編譯方法,節省時間:只有在多次使用某一個相同的正則運算式的時候,這個compile才會幫助我們提高程式的效率
        語法: obj = re.compile(pattern, flags) # 獲取正則運算式物件,引數一是正則運算式,引數二是功能標志位,提供更豐富的匹配
        回傳物件語法: res = obj.findall(string, pos, endpos) # 通過正則運算式匹配字串,匹配到的所有結果以串列回傳
        回傳物件語法引數: string: 目標字串; pos: 目標字串的匹配開始位置; endpos: 目標字串的匹配結束位置

import re

com = re.compile("\d+")
ret = com.findall("avc11sss22ssgg33")
print(ret)  # ['11', '22', '33']

pattern = r"(?P<name1>ab)cd(?P<name2>ab)"
# 獲取正則運算式compile物件
compile_obj = re.compile(pattern, flags=0)

# ########compile物件屬性########
# 標志位常量
print(compile_obj.flags)  # 32
# 正則運算式
print(compile_obj.pattern)  # (?P<name1>ab)cd(?P<name2>ab)
# 捕獲組字典
print(compile_obj.groupindex)  # {'name1': 1, 'name2': 2}
# 子組個數
print(compile_obj.groups)  # 2

# compile查找方法回傳一個match物件
match_obj = compile_obj.search("abcdefabcdabcdefabcde", 6, 15)

# ########match物件屬性########
# 目標字串開頭位置
print(match_obj.pos)  # 6
# 目標字串結束位置
print(match_obj.endpos)  # 15
# 正則運算式物件
print(match_obj.re)  # re.compile('(?P<name1>ab)cd(?P<name2>ab)')
# 目標字串
print(match_obj.string)  # abcdefabcdabcdefabcde
# 分組最后一組名字
print(match_obj.lastgroup)  # name2
# 分組最后一組是第幾組
print(match_obj.lastindex)  # 2

# ########match物件方法########
# 匹配到內容的開始位置
print(match_obj.start())  # 6
# 匹配到內容的結束位置
print(match_obj.end())  # 12
# 匹配到內容的起止位置
print(match_obj.span())  # (6, 12)
# 獲取match物件匹配的內容,引數默認為0表示獲取正則整體的匹配內容
print(match_obj.group())  # abcdab
# 引數為大于0的正整數表示獲取對應子組匹配內容
print(match_obj.group(1))  # ab
# 得到所有子組匹配的內容,元祖形式回傳
print(match_obj.groups())  # ('ab', 'ab')
# 得到所有捕獲組匹配到的內容,字典形式回傳
print(match_obj.groupdict())  # {'name1': 'ab', 'name2': 'ab'}

    8.爬蟲效率方法: finditer
        概述: finditer方法處理后回傳迭代器, 空間效率: 節省記憶體
        語法: ret = re.finditer(pattern, string, flags) # 使用正則運算式匹配目標內容回傳迭代物件,迭代的每個內容為一個math物件
        引數: pattern: 正則運算式; string: 目標字串; flags: 功能標識位

import re

ret = re.finditer("\d+", "asd22sa33")
print(ret)  # <callable_iterator object at 0x0000000003548BE0>
print(next(ret).group())  # 22
print(next(ret).group())  # 33

    9.引數flags
        概述: 輔助正則運算式,豐富匹配結果
        選項值:
            A, ASCII: 匹配ASCII字符
            S, DOTALL: 對元字符.起作用,讓其可以匹配換行
            I, IGNORECASE: 匹配時忽略大小寫
            L, LOCALE: 影響 “w, “W, “b, “B,做本地化識別(locale-aware)匹配
            M, MULTILINE: 可以匹配每一行的開頭結尾,影響 ^ 和 $
            T, TEMPLATE
            U, UNICODE: 根據Unicode字符集決議字符,這個標志影響 \w, \W, \b, \B
            X, VERBOSE: 為正則運算式添加注釋

import re

res = re.findall("h\w+", "Hello World!", re.I)  # 忽略大小寫
print(res)  # ['Hello']

res = re.findall(".+", "Hello\r\nWorld!", re.S)  # 忽略大小寫
print(res)  # ['Hello\r\nWorld!']

s = """hello world!
Hello Echo!
this is Tom 
"""
res = re.findall("^h\w+", s, re.M | re.I)  # 可以匹配每一行的開頭結尾
print(res)  # ['hello', 'hello']

pattern = """(?P<name>hello) # name組
\s+ # 空白字符
(world!) # 第二個分組
"""
res = re.findall(pattern, s, re.X)  # 為正則運算式添加注釋
print(res)  # [('hello', 'world!')]

    10.re模塊sub替換方法的高級用法

import re


def add(temp):
    str_num = temp.group()
    num = int(str_num) + 1
    return str(num)


ret = re.sub(r"\d+", add, "python = 997")
print(ret)  # python = 998

ret = re.sub(r"\d+", add, "python = 99")
print(ret)  # python = 100
    print(getAddress(port))

    11.正則匹配介面檔案地址示例
        1.介面檔案檔案: 1.txt

RP/0/RSP0/CPU0:2_c-leaf-1#  show interfaces
Thu Sep  7 15:17:18.514 UTC

BVI1 is down, line protocol is down
  Interface state transitions: 0
  Hardware is Bridge-Group Virtual Interface, address is 10f3.116c.e6a7
  Internet address is 192.168.100.254/24
  MTU 1514 bytes, BW 10000000 Kbit (Max: 10000000 Kbit)
     reliability 255/255, txload 0/255, rxload 0/255
  Encapsulation ARPA,  loopback not set,
  ARP type ARPA, ARP timeout 04:00:00
  Last input never, output never
  Last clearing of "show interface" counters never
  5 minute input rate 0 bits/sec, 0 packets/sec
  5 minute output rate 0 bits/sec, 0 packets/sec
     0 packets input, 0 bytes, 0 total input drops
     0 drops for unrecognized upper-level protocol
     Received 0 broadcast packets, 0 multicast packets
     0 packets output, 0 bytes, 0 total output drops
     Output 0 broadcast packets, 0 multicast packets

TenGigE0/0/2/3 is administratively down, line protocol is administratively down
  Interface state transitions: 0
  Hardware is TenGigE, address is 10f3.114b.978f (bia 10f3.114b.978f)
  Layer 1 Transport Mode is LAN
  Internet address is Unknown
  MTU 1514 bytes, BW 10000000 Kbit (Max: 10000000 Kbit)
     reliability 255/255, txload 0/255, rxload 0/255
  Encapsulation ARPA,
  Full-duplex, 10000Mb/s, SR, link type is force-up
  output flow control is off, input flow control is off
  Carrier delay (up) is 10 msec
  loopback not set,
  Last input 8w2d, output never
  Last clearing of "show interface" counters never
  5 minute input rate 0 bits/sec, 0 packets/sec
  5 minute output rate 0 bits/sec, 0 packets/sec
     51 packets input, 3372 bytes, 0 total input drops
     0 drops for unrecognized upper-level protocol
     Received 0 broadcast packets, 51 multicast packets
              0 runts, 0 giants, 0 throttles, 0 parity
     0 input errors, 0 CRC, 0 frame, 0 overrun, 0 ignored, 0 abort
     0 packets output, 0 bytes, 0 total output drops
     Output 0 broadcast packets, 0 multicast packets
     0 output errors, 0 underruns, 0 applique, 0 resets
     0 output buffer failures, 0 output buffers swapped out
     0 carrier transitions

        2.腳本檔案: demo1.py

import re
import sys


def getAddress(port):
    pattern = r'^\S+'
    f = open('1.txt', 'r')
    while True:
        data = ''
        for line in f:
            if line != '\n':
                data += line
            else:
                break
        if not data:
            break
        PORT = re.match(pattern, data).group()
        if port == PORT:
            pattern = r'address is (\S+)'
            addr = re.search(pattern, data).group(1)
            return addr
        else:
            continue


if __name__ == '__main__':
    # 運行方式: python3 demo1.py BVI1
    port = sys.argv[1]
    print(getAddress(port))

5.時間相關模塊 time

    1.time模塊概述:
        1.time模塊常應用于轉換時間格式和延時,如果年份小于100會自動轉換為加上1900后的值
        2.UTC: 國際標準時間,DST: 陽光節約時間,也叫夏令時,夏令修正時間(-1, 0 or 1)
        3.匯入語法: import time
        4.格式化時間字串:
            %y: 兩位數的年份表示(00-99)
            %Y: 四位數的年份表示(000-9999)
            %m: 月份(01-12)
            %d: 月內中的一天(0-31)
            %H: 24小時制小時數(0-23)
            %I: 12小時制小時數(01-12)
            %M: 分鐘數(00=59)
            %S: 秒(00-59)
            %a: 本地簡化星期名稱
            %A: 本地完整星期名稱
            %b: 本地簡化的月份名稱
            %B: 本地完整的月份名稱
            %c: 本地相應的日期表示和時間表示
            %j: 年內的一天(001-366)
            %p: 本地A.M.或P.M.的等價符
            %U: 一年中的星期數(00-53)星期天為星期的開始
            %w: 星期(0-6),星期天為星期的開始,0代表星期一
            %W: 一年中的星期數(00-53)星期一為星期的開始
            %x: 本地相應的日期表示
            %X: 本地相應的時間表示
            %Z: 當前時區的名稱
            %%: %號本身
        5.struct_time元組共有9個元素共九個元素:(年,月,日,時,分,秒,星期幾,一年中第幾天,是否是夏令時)

 索引  屬性(Attribute) 值(Values)
0 tm_year(年) 比如2011
1 tm_mon(月) 1 - 12
2 tm_mday(日) 1 - 31
3 tm_hour(時) 0 - 23
4 tm_min(分) 0 - 59
5 tm_sec(秒) 0 - 60
6 tm_wday(星期幾)  0 - 6(0表示周一) 
7  tm_yday(一年中的第幾天)  1 - 366
8 tm_isdst(是否是夏令時) 默認為0

    2.模塊名.屬性

import time

# 夏令時時間與UTC時間差(秒為單位)
time.altzone  # -28800

# 夏令時校正時間
time.daylight  # 0

# 本地區時間與UTC時間差(秒為單位)
time.timezone  # -28800

# 時區名字的元組,第一個名字為未經夏令時修正的時區名,第二個名字為經夏令時修正后的時區名
time.tzname  # ('CST', 'CST')

    3.模塊名.方法-取時間(time, localtime, gmtime)

import time

# time()取時間戳-->做計算
print(time.time())  # 1553274079.3324106秒-->1970年凌晨到現在的時間經過了多少秒

# localtime結構化時間-->當地時間
t = time.localtime()  # 默認引數time.time()
print(t)
"""執行結果
    time.struct_time(tm_year=2020, tm_mon=5, tm_mday=31, 
    tm_hour=11, tm_min=45, tm_sec=51, 
    tm_wday=6, tm_yday=152, tm_isdst=0)
"""
# 列印年
print(t.tm_year)  # 2020

# gmtime結構化時間-->UTC世界標準時間, 比中國時間慢8小時
print(time.gmtime())  # 格林時間
"""執行結果
    time.struct_time(tm_year=2020, tm_mon=5, tm_mday=31, 
    tm_hour=3, tm_min=48, tm_sec=16, 
    tm_wday=6, tm_yday=152, tm_isdst=0)
"""

    4.模塊名.方法-格式轉換(localtime, gmtime, mktime, strftime strptime, asctime, ctime)

import time

# 時間戳轉結構化時間
#time.gmtime(時間戳): UTC時間,與英國倫敦當地時間一致
#time.localtime(時間戳): 當地時間,在北京執行這個方法與UTC時間相差8小時,UTC時間+8小時 = 北京時間
time.gmtime(1500000000)
"""執行結果
    time.struct_time(tm_year=2017, tm_mon=7, tm_mday=14, tm_hour=2, tm_min=40, 
    tm_sec=0, tm_wday=4, tm_yday=195, tm_isdst=0)
"""
time.localtime(1500000000)
"""執行結果
    time.struct_time(tm_year=2017, tm_mon=7, tm_mday=14, tm_hour=10, tm_min=40, 
    tm_sec=0, tm_wday=4, tm_yday=195, tm_isdst=0)
"""

# mktime結構化時間轉換成時間戳
print(time.mktime(t))
time.mktime(time.localtime(15000))  # 15000.0

# strftime結構化時間轉換成字串時間
# Y年 m月 d日 X時分秒 t結構化時間
print(time.strftime("%Y-%m-%d %X", t))  # 2020-05-31 11:45:51

# strptime將字串時間轉換成結構化時間
print(time.strptime("2019:03:23:01:26:11", "%Y:%m:%d:%X"))
"""print(time.strptime("2019:03:23:01:26:11", "%Y:%m:%d:%X"))執行結果
    time.struct_time(tm_year=2019, tm_mon=3, tm_mday=23, 
    tm_hour=1, tm_min=26, tm_sec=11, 
    tm_wday=5, tm_yday=82, tm_isdst=-1)
"""

# asctime()將結構化時間轉換成固定的字串表達方式-->默認引數取當前結構化時間
#  周月日時分秒年
print(time.asctime())  # Sun May 31 11:52:22 2020

# ctime()將時間戳時間轉換成固定的字串表達方式-->默認引數取當前時間戳
#  周月日時分秒年
print(time.ctime())  # Sun May 31 11:52:48 2020

    5.模塊名.方法-時間延時(sleep)

import time

# sleep()執行緒推遲指定時間運行,單位秒
time.sleep(1)  # 睡一秒

    6.模塊名.方法-計算時間差(mktime, gmtime)

import time

true_time = time.mktime(time.strptime("2017-09-11 08:30:00", "%Y-%m-%d %H:%M:%S"))
time_now = time.mktime(time.strptime("2017-09-12 11:00:00", "%Y-%m-%d %H:%M:%S"))
dif_time = time_now - true_time
struct_time = time.gmtime(dif_time)
print("過去了%d年%d月%d天%d小時%d分鐘%d秒" % (struct_time.tm_year - 1970,
                                   struct_time.tm_mon - 1,
                                   struct_time.tm_mday - 1,
                                   struct_time.tm_hour,
                                   struct_time.tm_min,
                                   struct_time.tm_sec))

6.時間相關模塊 datetime

    1.模塊名.方法-取時間(now, utcnow)

from datetime import datetime

# 獲取當前本地時間
a = datetime.now()
print("當前日期:", a)  # 當前日期: 2020-06-23 07:13:55.317040

# 獲取當前世界時間
b = datetime.utcnow()
print("世界時間:", b)  # 世界時間: 2020-06-22 23:13:55.317154

# 用指定日期創建datetime型別時間
c = datetime(2018, 5, 27, 16, 30)
print("指定日期:", c)  # 指定日期: 2018-05-27 16:30:00

    2.模塊名.方法-型別轉換(strptime, strftime)

from datetime import datetime

# 字串轉換成datetime型別
d = datetime.strptime("2018/9/30", "%Y/%m/%d")
print(d)  # 2018-09-30 00:00:00
e = datetime.strptime("2018年9月30日星期六", "%Y年%m月%d日星期六")
print(e)  # 2018-09-30 00:00:00
f = datetime.strptime("2018年9月30日星期六8時42分24秒", "%Y年%m月%d日星期六%H時%M分%S秒")
print(f)  # 2018-09-30 08:42:24
g = datetime.strptime("9/30/2018", "%m/%d/%Y")
print(g)  # 2018-09-30 00:00:00
h = datetime.strptime("9/30/2018 8:42:50 ", "%m/%d/%Y %H:%M:%S ")
print(h)  # 2018-09-30 08:42:50

# datetime型別轉換成字串
i = datetime(2018, 9, 28, 10, 3, 43)
print(i.strftime("%Y年%m月%d日%A,%H時%M分%S秒"))  # 2018年09月28日Friday,10時03分43秒
j = datetime(2018, 9, 30, 10, 3, 43)
print(j.strftime("%A,%B %d,%Y"))  # Sunday,September 30,2018
k = datetime(2018, 9, 30, 9, 22, 17)
print(k.strftime("%m/%d/%Y %I:%M:%S%p"))  # 09/30/2018 09:22:17AM
l = datetime(2018, 9, 30)
print(l.strftime("%B %d,%Y"))  # September 30,2018

    3.模塊名.方法-時間截取(strftime)

from datetime import datetime

m = datetime.now()  # 獲取當前系統時間
print(m.strftime("今天是%Y年%m月%d日"))  # 今天是2020年06月23日
print(m.strftime("今天是這周的第%w天"))  # 今天是這周的第2天
print(m.strftime("今天是今年的第%j天"))  # 今天是今年的第175天
print(m.strftime("今周是今年的第%W周"))  # 今周是今年的第25周
print(m.strftime("今天是當月的第%d天"))  # 今天是當月的第23天

    4.時間加減和替換

import datetime

print(datetime.datetime.now())  # 2020-06-22 21:08:43.500433
# 時間戳直接轉成日期格式
print(datetime.date.fromtimestamp(time.time()))  # 2020-06-22

# 回傳當前系統時間
print(datetime.datetime.now())  #  2020-06-22 21:08:43.500485
# 當前時間+3天
print(datetime.datetime.now() + datetime.timedelta(3))  # 2020-06-25 21:08:43.500491
#  當前時間-3天
print(datetime.datetime.now() + datetime.timedelta(-3))  # 2020-06-19 21:08:43.500503
# 當前時間+3小時 
print(datetime.datetime.now() + datetime.timedelta(hours=3))  # 2020-06-23 00:08:43.500508
# 當前時間+30分
print(datetime.datetime.now() + datetime.timedelta(minutes=30))  # 2020-06-22 21:38:43.500516

#  時間替換
c_time = datetime.datetime.now()
print(c_time.replace(minute=3, hour=2))  # 2020-06-22 02:03:43.500522

7.序列化模塊 json

    1.json模塊概述
        json用于字串和Python資料型別間進行轉換,set資料型別不能被dump/dumps,json格式中的字串只能是""
        匯入語法: import json

    2.dump方法和load方法

import json

# json格式的key必須是字串資料型別,如果是數字為key,那么dump之后會強行轉成字串資料型別
dic = {1:2,3:4}
str_dic = json.dump(dic)  # 轉換成所有語言都支持的json的字串
print(str_dic)  # {"1": 2, "3": 4}
new_dic = json.load(str_dic)  # # 將json處理的字串還原原來的資料型別
print(new_dic)  # {'1': 2, '3': 4}

# 單次dump資料到檔案里,單次從檔案中load出來
f = open('json_file', 'w')
dic = {'k1': 'v1', 'k2': 'v2', 'k3': 'v3'}
json.dump(dic, f)  # dump方法接收一個檔案句柄,直接將字典轉換成json字串寫入檔案
f.close()
f = open('json_file')
dic2 = json.load(f)  # load方法接收一個檔案句柄,直接將檔案中的json字串轉換成資料結構回傳
f.close()
print(type(dic2), dic2)  # <class 'dict'> {'k1': 'v1', 'k2': 'v2', 'k3': 'v3'}

# 對串列的dump
lst = ['aaa', 123, 'bbb', 12.456]
with open('json_demo', 'w') as f:
    json.dump(lst, f)
with open('json_demo') as f:
    ret = json.load(f)
    print(ret)  # ['aaa', 123, 'bbb', 12.456]

# 能不能多次dump資料到檔案里,可以多次dump但是不能load出來
dic = {'abc': (1, 2, 3)}
lst = ['aaa', 123, 'bbb', 12.456]
with open('json_demo', 'w') as f:
    json.dump(lst, f)
    json.dump(dic, f)
with open('json_demo') as f:
    ret = json.load(f)  # 拋出例外: json.decoder.JSONDecodeError
    print(ret)

    3.dumps方法和loads方法

import json

# json對元組做value的字典會把元組強制轉換成串列
dic = {'abc':(1,2,3)}
str_dic = json.dumps(dic)
print(str_dic)  # {"abc": [1, 2, 3]}
new_dic = json.loads(str_dic)
print(new_dic)  # {'abc': [1, 2, 3]}

# json不支持元組做key操作
dic = {(1,2,3):'abc'}
str_dic = json.dumps(dic)  # 報錯

# 用dumps將多個資料寫進入檔案
dic = {'abc': (1, 2, 3)}
lst = ['aaa', 123, 'bbb', 12.456]
with open('json_demo', 'w') as f:
    str_lst = json.dumps(lst)
    str_dic = json.dumps(dic)
    f.write(str_lst + '\n')
    f.write(str_dic + '\n')

with open('json_demo') as f:
    for line in f:
        ret = json.loads(line)
        print(ret)  # ['aaa', 123, 'bbb', 12.456] {'abc': [1, 2, 3]} 

# 序列化: 將一個字典轉換成一個字串,json轉換完的字串型別的字典中的字串是由""表示的
dic = {'k1':'v1','k2':'v2','k3':'v3'}
str_dic = json.dumps(dic)  
print(type(str_dic),str_dic)  # <class 'str'> {"k3": "v3", "k1": "v1", "k2": "v2"}

# 反序列化: 將一個字串格式的字典轉換成一個字典,json處理的字串型別的字典中的字串必須由""表示
dic2 = json.loads(str_dic)
print(type(dic2),dic2)  # <class 'dict'> {'k1': 'v1', 'k2': 'v2', 'k3': 'v3'}

# 處理嵌套的資料型別
list_dic = [1,['a','b','c'],3,{'k1':'v1','k2':'v2'}]
str_dic = json.dumps(list_dic)
print(type(str_dic),str_dic)  # <class 'str'> [1, ["a", "b", "c"], 3, {"k1": "v1", "k2": "v2"}]
list_dic2 = json.loads(str_dic)
print(type(list_dic2),list_dic2)  # <class 'list'> [1, ['a', 'b', 'c'], 3, {'k1': 'v1', 'k2': 'v2'}]

    4.其他引數說明
        Skipkeys
            默認值是False,dict的keys內的資料不是python的基本型別(str,unicode,int,long,float,bool,None)
            設定為False時,會報TypeError的錯誤,此時設定成True,則會跳過這類key
        ensure_ascii
            當它為True的時候,所有非ASCII碼字符顯示為"\uXXXX"序列,只需在dump時將ensure_ascii設定為False即可,
            此時存入json的中文即可正常顯示
        indent
            應該是一個非負的整型,如果是0就是頂格分行顯示,如果為空就是一行最緊湊顯示,否則會換行且按照indent的數值顯示前面的空白分行顯示,
            這樣列印出來的json資料也叫pretty-printed json
        separators
            分隔符,實際上是(item_separator, dict_separator)的一個元組,默認的就是(',', ':'),這表示dictionary內keys之間用','隔開,
            而KEY和value之間用':'隔開
        sort_keys: 將資料根據keys的值進行排序

import json

f = open('file', 'w')
json.dump({'國籍': '中國'}, f)
ret = json.dumps({'國籍': '中國'})
f.write(ret + '\n')
json.dump({'國籍': '美國'},f, ensure_ascii=False)
ret = json.dumps({'國籍': '美國'}, ensure_ascii=False)
f.write(ret + '\n')
f.close()

    5.json格式化輸出

# 不推薦使用,是為了用戶看的更方便,但是會相對浪費存盤空間
import json

data = {'username': ['湯姆貓', '傻傻的'], 'sex': 'male', 'age': 16}
jn_dic = json.dumps(data,sort_keys=True, indent=2, separators=(',', ':'), ensure_ascii=False)
print(jn_dic)
"""執行結果
    {
      "age":16,
      "sex":"male",
      "username":[
        "湯姆貓",
        "傻傻的"
      ]
    }
"""

8.序列化模塊 pickle

    1.pickle模塊概述
        pickle 用于python特有的型別和python的資料型別間進行轉換,對于多次dump/load的操作做了良好的處理
        pickle 將資料轉換成位元組,還支持函式和類的轉換,對于物件的序列化需要這個物件對應的類在記憶體中
        pickle 的dump結果是bytes,dump用的f檔案句柄需要以wb的形式打開,load所用的f是'rb'模式
        匯入語法: import pickle

    2.dump方法和load方法

# pickle模塊來存盤每個學員的物件
import pickle

with open('pickle_demo','wb') as f:
    pickle.dump({'k1': 'v1'}, f)
    pickle.dump({'k11': 'v1'}, f)
    pickle.dump({'k11': 'v1'}, f)
    pickle.dump({'k12': [1,2,3]}, f)
    pickle.dump(['k1','v1','l1'], f)

with open('pickle_demo','rb') as f:
    while True:
        try:
            print(pickle.load(f))
        except EOFError:
            break
"""執行結果
    {'k1': 'v1'}
    {'k11': 'v1'}
    {'k11': 'v1'}
    {'k12': [1, 2, 3]}
    ['k1', 'v1', 'l1']
"""

# pickle支持幾乎所有物件的
import pickle

class Student:
    def __init__(self, name, age):
        self.name = name
        self.age = age


Tom = Student('Tom',13)
with open('pickle_demo', 'wb') as f:
    pickle.dump(Tom,f)
with open('pickle_demo', 'rb') as f:
    Cat = pickle.load(f)
    print(Cat.name)  # Tom
    print(Cat.age)  # 13

    3.dumps方法和loads方法

import pickle

dic1 = {"name": "coco"}
data2 = pickle.dumps(dic1)  # 轉換成所有語言都支持的pickle的bytes
print(data2)  # b'\x80\x03}q\x00X\x04\x00\x00\x00nameq\x01X\x04\x00\x00\x00cocoq\x02s.'
print(type(data2))  # <class 'bytes'>
f1 = open("test3", "wb")
# data = https://www.cnblogs.com/tangxuecheng/p/pickle.dump(dic1, f)  # 直接轉化寫入檔案
f1.write(data2)
f1.close()

f1_read = open("test3", "rb")
data3 = pickle.loads(f1_read.read())  # 將pickle處理的bytes還原原來的資料型別
# data3 = pickle.load(f)  # 直接讀取還原
print(data3)  # {'name': 'coco'}
print(type(data3))  # <class 'dict'>
f1_read.close()

9.序列化讀檔案模塊 shelve

    1.shelve模塊概述:
        檔案改動的比較少,讀檔案的操作比較多,且大部分讀取都需要基于某個key獲得某個value時推薦使用shelve模塊
        匯入語法: import shelve

import shelve

f = shelve.open(r"shelve.txt")  # 生成一個空文本
f["stu1_info"] = {"name": "coco", "age": "26"}  # 將字典放入文本
f["stu2_info"] = {"name": "angels", "age": "18"}

print(f.get("stu1_info")["name"])   # coco
print(f.get("stu2_info")["age"])  # 18
f.close()

10.演算法摘要模塊 hashlib

import hashlib

# md5
# md5是一個演算法,32位的字串,每個字符都是一個十六進制
# md5演算法 效率快 演算法相對簡單
obj = hashlib.md5("ssasdf".encode(encoding="utf8"))  # 自定義加鹽
obj.update("coco".encode(encoding="utf8"))  # 原生md5加密
print(obj.hexdigest())  # 516dacada2fea0112265e3a474dee5fe

# sha256
obj = hashlib.sha256("ssasdf".encode(encoding="utf8"))  # 自定義加鹽
obj.update("coco".encode(encoding="utf8"))  # 原生md5加密
print(obj.hexdigest())  # 577cce053410c4bf7ccee892b3d92c55f20c56b773276a326777a4535a021909

# sha1也是一個演算法,40位的字串,每個字符都是一個十六進制
# 演算法相對復雜 計算速度也慢
s1 = "fadfasvfdfsf"
sha1_obj = hashlib.sha1()
sha1_obj.update(s1.encode('utf-8'))
res = sha1_obj.hexdigest()
print(res,len(res), type(res))  # a794b78d12fd18898d65e1b4ff320f44f7dbe2a9 40 <class 'str'>

# 動態加鹽
username = input('username : ')
passwd = input('password : ')
md5obj = hashlib.md5(username.encode('utf-8'))
md5obj.update(passwd.encode('utf-8'))
print(md5obj.hexdigest())  # ee838c58e5bb3c9e687065edd0ec454f

# 檔案的一致性校驗
md5_obj = hashlib.md5()
with open('5.序列化模塊_shelve.py', 'rb') as f:
    md5_obj.update(f.read())
    ret1 = md5_obj.hexdigest()

md5_obj = hashlib.md5()
with open('5.序列化模塊_shelve.py.bak', 'rb') as f:
    md5_obj.update(f.read())
    ret2 = md5_obj.hexdigest()
print(ret1,ret2)

# 大檔案的一致性校驗
md5_obj = hashlib.md5()
with open('5.序列化模塊_shelve.py.bak', 'rb') as f:
    md5_obj.update(f.read(10240))
    # 回圈 回圈的讀取檔案內容
    # 回圈的來update
print(md5_obj.hexdigest())

# 模擬撞庫破解密碼
    import hashlib

    passwds = [
        'alex3714',
        'alex1313',
        'alex94139413',
        'alex123456',
        '123456alex',
        'a123lex',
    ]


    def make_passwd_dic(passwds):
        dic = {}
        for passwd in passwds:
            m = hashlib.md5()
            m.update(passwd.encode('utf-8'))
            dic[passwd] = m.hexdigest()
        return dic


    def break_code(cryptograph, passwd_dic):
        for k, v in passwd_dic.items():
            if v == cryptograph:
                print('密碼是===>\033[46m%s\033[0m' % k)


    cryptograph = 'aee949757a2e698417463d47acac93df'
    break_code(cryptograph, make_passwd_dic(passwds))

11.日志模塊 logging

    1.日志從低到高的五個級別
        DEBUG: 除錯模式,詳細的資訊,通常只出現在診斷問題上
        INFO: 基礎資訊,確認一切按預期運行
        WARNING: 警告,一個跡象表明一些意想不到的事情發生了,或表明一些問題在不久的將來例如磁盤空間低,這個軟體還能按預期作業
        ERROR: 錯誤,更嚴重的問題,軟體沒能執行一些功能
        CRITICAL: 嚴重錯誤: 一個嚴重的錯誤,這表明程式本身可能無法繼續運行

    2.配置日志的兩種方式

        1.basicConfig定義日志

import logging

logging.basicConfig(
    level=logging.DEBUG,  # 設定顯示日志級別
    filename="./logger.log",  # 設定寫出日志路徑
    filemode="w",  # 覆寫寫入
    format="%(asctime)s - %(filename)s[line:%(lineno)d] - %(levelname)s: %(message)s"  # 設定寫出格式
)

# 日志
logging.debug("debug message")  # 除錯模式
logging.info("info message")  # 基礎資訊
logging.warning("warning massage")  # 警告
logging.error("error massage")  # 錯誤
logging.critical("critical massage")  # 嚴重錯誤
"""執行結果: 當前路徑下生成logger.log檔案
    2020-07-11 23:12:49,453 - test_log1.py[line:12] - DEBUG: debug message
    2020-07-11 23:12:49,453 - test_log1.py[line:13] - INFO: info message
    2020-07-11 23:12:49,453 - test_log1.py[line:14] - WARNING: warning massage
    2020-07-11 23:12:49,453 - test_log1.py[line:15] - ERROR: error massage
    2020-07-11 23:12:49,454 - test_log1.py[line:16] - CRITICAL: critical massage
"""

        2.getLogger創建物件定義日志

def set_logger():
    # 第一步,創建一個logger
    set_log = logging.getLogger()  # 創建一個logger物件
    set_log.setLevel(logging.INFO)  # 設定Log等級總開關,默認的是WARNING

    # 第二步,創建一個handler檔案管理運算子,用于寫入日志檔案
    logfile = './log.txt'
    fh = logging.FileHandler(logfile, mode='a')  # open的打開模式這里可以進行參考
    fh.setLevel(logging.DEBUG)  # 輸出到file的log等級的開關

    # 第三步,再創建一個handler螢屏管理運算子,用于輸出到控制臺
    ch = logging.StreamHandler()
    ch.setLevel(logging.WARNING)  # 輸出到console的log等級的開關

    # 第四步,定義handler的輸出格式
    formatter = logging.Formatter("%(asctime)s - %(filename)s[line:%(lineno)d] - %(levelname)s: %(message)s")
    fh.setFormatter(formatter)  # 檔案管理運算子 系結一個 格式
    ch.setFormatter(formatter)  # 螢屏管理運算子 系結一個 格式

    # 第五步,將logger添加到handler里面
    set_log.addHandler(fh)  # logger物件 系結 檔案管理運算子
    set_log.addHandler(ch)  # logger物件 系結 螢屏管理運算子

    return set_log


# 日志
logger = set_logger()
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')
"""
    2020-07-11 23:10:08,934 - test_log2.py[line:34] - INFO: 這是 logger info message
    2020-07-11 23:10:08,934 - test_log2.py[line:35] - WARNING: 這是 logger warning message
    2020-07-11 23:10:08,934 - test_log2.py[line:36] - ERROR: 這是 logger error message
    2020-07-11 23:10:08,934 - test_log2.py[line:37] - CRITICAL: 這是 logger critical message
"""

    2.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 = '%(asctime)s - %(filename)s[line:%(lineno)d] - %(levelname)s: %(message)s'

    3.format引數中可能用到的格式化串
        %(name)s: Logger的名字
        %(levelno)s: 數字形式的日志級別
        %(levelname)s: 文本形式的日志級別
        %(pathname)s: 呼叫日志輸出函式的模塊的完整路徑名,可能沒有,其實就是sys.argv[0]
        %(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: 用戶輸出的訊息即日志資訊

    4.日志切割

import logging
import time
from logging import handlers

sh = logging.StreamHandler()
rh = handlers.RotatingFileHandler('myapp.log', maxBytes=1024, backupCount=5)
fh = handlers.TimedRotatingFileHandler(filename='x2.log', when='s', interval=5, encoding='utf-8')
logging.basicConfig(
    format='%(asctime)s - %(name)s - %(levelname)s -%(module)s: %(message)s',
    datefmt='%Y-%m-%d %H:%M:%S %p',
    handlers=[fh, sh, rh],
    level=logging.ERROR
)

for i in range(1, 100000):
    time.sleep(1)
    logging.error('KeyboardInterrupt error %s' % str(i))

    5.django中的日志配置

# logging_config.py
LOGGING = {
    'version': 1,  # 保留字
    'disable_existing_loggers': False,  # 禁用已經存在的logger實體
    'formatters': {
        # 詳細的日志格式
        'standard': {
            'format': '[%(asctime)s][%(threadName)s:%(thread)d][task_id:%(name)s]''[%(filename)s:%(lineno)d]'
                      '[%(levelname)s][%(message)s]'
        },
        # 簡單的日志格式
        'simple': {
            'format': '[%(levelname)s][%(asctime)s][%(filename)s:%(lineno)d]%(message)s'
        },
        # 定義一個特殊的日志格式
        'collect': {
            'format': '%(message)s'
        }
    },
    # 過濾器
    'filters': {
        'require_debug_true': {
            '()': 'django.utils.log.RequireDebugTrue',
        },
    },
    # 處理器,定義具體處理日志的方式
    'handlers': {
        # 列印到終端的日志
        'console': {
            'level': 'DEBUG',
            'filters': ['require_debug_true'],  # 只有在Django debug為True時才在螢屏列印日志
            'class': 'logging.StreamHandler',
            'formatter': 'simple'
        },
        # 列印到檔案的日志,收集info及以上的日志
        'default': {
            'level': 'INFO',
            'class': 'logging.handlers.RotatingFileHandler',  # 保存到檔案,自動切
            'filename': os.path.join(BASE_LOG_DIR, "xxx_info.log"),  # 日志檔案
            'maxBytes': 1024 * 1024 * 5,  # 日志大小 5M
            'backupCount': 3,  # 最多備份幾個
            'formatter': 'standard',  # 輸出格式
            'encoding': 'utf-8',
        },
        # 列印到檔案的日志:收集錯誤及以上的日志
        'error': {
            'level': 'ERROR',
            'class': 'logging.handlers.RotatingFileHandler',  # 保存到檔案,自動切
            'filename': os.path.join(BASE_LOG_DIR, "xxx_err.log"),  # 日志檔案
            'maxBytes': 1024 * 1024 * 5,  # 日志大小 5M
            'backupCount': 5,
            'formatter': 'standard',
            'encoding': 'utf-8',
        },
        # 列印到檔案的日志
        'collect': {
            'level': 'INFO',
            'class': 'logging.handlers.RotatingFileHandler',  # 保存到檔案,自動切
            'filename': os.path.join(BASE_LOG_DIR, "xxx_collect.log"),
            'maxBytes': 1024 * 1024 * 5,  # 日志大小 5M
            'backupCount': 5,
            'formatter': 'collect',
            'encoding': "utf-8"
        }
    },
    'loggers': {
        # logging.getLogger(__name__)拿到的logger配置
        '': {
            'handlers': ['default', 'console', 'error'],
            'level': 'DEBUG',
            'propagate': True,  # 向不向更高級別的logger傳遞
        },
        # logging.getLogger('collect')拿到的logger配置
        'collect': {
            'handlers': ['console', 'collect'],
            'level': 'INFO',
        }
    },
}

# 用法:拿到倆個logger
logger = logging.getLogger(__name__)  # 線上正常的日志
collect_logger = logging.getLogger("collect")  # 為領導們單獨定制領導們看的日志

12.組態檔模塊 configparser

import configparser

config = configparser.ConfigParser()

config["DEFAULT"] = {
    "Sever": "45",
    "Compression": "yes",
    "CompressionLevel": "9"
}

config["bt.org"] = {}
config["bt.org"]["User"] = "coco"

config["sever.com"] = {}
top = config["sever.com"]
top["Host Ip"] = "127.0.0.1"
top["Host Port"] = "8080"

with open("example.ini", "w") as configfile:
    config.write(configfile)

# 查組態檔
config.read("example.ini")
print(config.sections())  # 讀除默認塊以外的塊名['bt.org', 'sever.com']
print(config["bt.org"]["user"])  # coco
for key in config:
    print(key)

print(config.options("bt.org"))  # ['user', 'sever', 'compression', 'compressionlevel']
print(config.items("bt.org"))  # [('sever', '45'), ('compression', 'yes'), ('compressionlevel', '9'), ('user', 'coco')]
print(config.get("bt.org", "user"))  # coco

# 添加,修改,洗掉
config.add_section("yun")  # 添加塊
config.set("yun", "k1", "11")  # 添加鍵值對,同名覆寫即修改
config.remove_option("sever.com", "host port")  # 洗掉塊下的某個鍵值對
config.remove_section("sever.com")  # 洗掉塊及塊里面的的所有鍵值對

config.write(open("i.cfg"), "w")
組態檔如下:
    # 注釋1
    # 注釋2

    [section1]
    k1 = v1
    k2:v2
    user=egon
    age=18
    is_admin=true
    salary=31

    [section2]
    k1 = v1
讀取組態檔:
    import configparser

    config = configparser.ConfigParser()
    config.read('a.cfg')

    # 查看所有的標題
    res = config.sections()  # ['section1', 'section2']
    print(res)

    # 查看標題section1下所有key=value的key
    options = config.options('section1')
    print(options)  # ['k1', 'k2', 'user', 'age', 'is_admin', 'salary']

    # 查看標題section1下所有key=value的(key,value)格式
    item_list = config.items('section1')
    print(item_list)
    # [('k1', 'v1'), ('k2', 'v2'), ('user', 'egon'), ('age', '18'), ('is_admin', 'true'), ('salary', '31')]

    # 查看標題section1下user的值=>字串格式
    val = config.get('section1', 'user')
    print(val)  # egon

    # 查看標題section1下age的值=>整數格式
    val1 = config.getint('section1', 'age')
    print(val1)  # 18

    # 查看標題section1下is_admin的值=>布林值格式
    val2 = config.getboolean('section1', 'is_admin')
    print(val2)  # True

    # 查看標題section1下salary的值=>浮點型格式
    val3 = config.getfloat('section1', 'salary')
    print(val3)  # 31.0
改寫組態檔:
    import configparser

    config = configparser.ConfigParser()
    config.read('a.cfg', encoding='utf-8')

    # 洗掉整個標題section2
    config.remove_section('section2')

    # 洗掉標題section1下的某個k1和k2
    config.remove_option('section1', 'k1')
    config.remove_option('section1', 'k2')

    # 判斷是否存在某個標題
    print(config.has_section('section1'))

    # 判斷標題section1下是否有user
    print(config.has_option('section1', ''))

    # 添加一個標題
    config.add_section('egon')

    # 在標題egon下添加name=egon,age=18的配置
    config.set('egon', 'name', 'egon')
    # config.set('egon', 'age', 18)  # 報錯,必須是字串

    # 最后將修改的內容寫入檔案,完成最終的修改
    config.write(open('a.cfg', 'w'))
添加ini檔案
    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'  # mutates the parser
    topsecret['ForwardX11'] = 'no'  # same here
    config['DEFAULT']['ForwardX11'] = 'yes'
    with open('example.ini', 'w') as configfile:
        config.write(configfile)

13.標記語言模塊 xml

import xml.etree.ElementTree as ET  # as 取別名

"""xml_lesson檔案
    <?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>
"""
tree = ET.parse("xml_lesson")  # parse決議xml,回傳一個決議物件
root = tree.getroot()  # getroot 取根節點
print(root.tag)  # tag 拿到根節點的標簽名

# 遍歷xml檔案
for child in root:
    print(child.tag, child.attrib)  # tag標簽名,attrib標簽屬性
    for i in child:
        print(i.tag, i.text)  # text標簽的內容

# 只遍歷year節點
for node in root.iter("year"):  # iter指定拿root根下的某個節點
    print(node.tag, node.text)

# 修改
for node in root.iter("year"):
    new_year = int(node.text) + 1  # 修改year標簽內容
    node.text = str(new_year)  # 重新賦值修改內容
    node.set("updated", "yes")  # 為year標簽添加屬性
tree.write("xml_lesson")  # 把修改后內容從新寫一個檔案,同名則覆寫原檔案

# 洗掉
for country in root.findall("country"):  # findall 找root的所有country標簽
    rank = int(country.find("rank").text)  # find 找country下的rank標簽
    if rank >= 50:
        root.remove(country)
tree.write("xml_output")  # 把修改后內容從新寫一個檔案,同名則覆寫原檔案

# 創建一個xml
new_xml = ET.Element("namelist")  # Element 創建根節點
name = ET.SubElement(new_xml, "name", attrib={"enrolled": "yes"})
age = ET.SubElement(name, "age", attrib={"checked": "no"})
sex = ET.SubElement(name, "sex")
sex.text = "26"

et = ET.ElementTree(new_xml)  # 生成檔案物件
et.write("xml_text.xml", encoding="utf-8", xml_declaration=True)  # 寫出到檔案
ET.dump(new_xml)  # 列印生成格式

14.資料型別模塊 collections

1.模塊概述: Python在內置資料型別的基礎上, collections模塊還提供了幾個額外的資料型別

        1.namedtuple: 生成可以使用名字來訪問元素內容的tuple
        2.deque: 雙端佇列,可以快速的從另外一側追加和推出物件
        3.Counter: 計數器,主要用來計數
        4.OrderedDict: 有序字典,在Python3.7之后的版本字典增加有序的特性
        5.defaultdict: 帶有默認值的字典

2.元祖的擴展 namedtuple

# 用來表示一個點的二維坐標
from collections import namedtuple

Point = namedtuple("Point", ["x", "y"])
p = Point(1, 2)
print(p.x, p.y)  # 1, 2
# 用坐標和半徑表示一個圓
from collections import namedtuple

# namedtuple("名稱", [屬性list]):
Circle = namedtuple("Circle", ["x", "y", "r"])

3.雙端佇列 deque

        deque模塊概述:
            1.使用list存盤資料時,按索引訪問元素快插入和洗掉元素慢,因為list是線性存盤,資料量大的時候,插入和洗掉效率很低
            2.deque是為了高效實作插入和洗掉操作的雙向串列,適合用于佇列和堆疊
            3.deque實作了: append(), pop(), appendleft(), popleft(), 可以非常高效地往頭部添加或洗掉元素
            4.在insert remove的時候 deque的平均效率要高于串列, 串列根據索引查看某個值的效率要高于deque
            5.匯入語法: from collections import deque

from collections import deque

q = deque(["a", "b", "c"])
q.append("x")
q.appendleft("y")
print(q)  # deque(["y", "a", "b", "c", "x"])
from collections import deque

dq = deque()
dq.append(2)
dq.append(5)
dq.appendleft("a")
dq.appendleft("b")
print(dq)  # deque(["b", "a", 2, 5])

# print(dq.pop())  # 5
# print(dq)  # deque(["b", "a", 2])
# print(dq.popleft())  # b
# print(dq)  # deque(["a", 2])

print(dq.remove("a"))  # None
print(dq.insert(2, "123"))  # None
print(dq)  # deque(["b", 2, "123", 5])

4.計數器 Counter

    Counter模塊概述:
        1.Counter類的目的是用來跟蹤值出現的次數,它是一個無序的容器型別
        2.以字典的鍵值對形式存盤,其中元素作為key,其計數作為value,計數值可以是任意的Interger(包括0和負數)
        3.匯入語法: from collections import Counter

from collections import Counter

c = Counter("abcdeabcdabcaba")
print(c)  # Counter({"a": 5, "b": 4, "c": 3, "d": 2, "e": 1})

5.有序字典 OrderedDict

# 保持字典Key的順序
from collections import OrderedDict

d = dict([("a", 1), ("b", 2), ("c", 3)])
print(d)  # dict的Key是無序的 {"a": 1, "c": 3, "b": 2}

od = OrderedDict([("a", 1), ("b", 2), ("c", 3)])
print(od)  # OrderedDict的Key是有序的 OrderedDict([("a", 1), ("b", 2), ("c", 3)])

6.帶有默認值的字典 defaultdict

    defaultdict字典概述:
        1.使用dict時如果參考的Key不存在就會拋出KeyError,如果希望key不存在時回傳一個默認值就可以用defaultdict
        2.匯入語法: from collections import defaultdict

# 將集合中所有大于 66 的值保存至字典的第一個key中,將小于 66 的值保存至第二個key的值中
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)
# 不使用默認字典實作方法
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

dd = defaultdict(lambda: "N/A")
dd["key1"] = "abc"
dd["key1"]  # key1存在回傳'abc'
dd["key2"]  # key2不存在,回傳默認值'1.1N/A'

15.高級的檔案,檔案夾,壓縮包處理模塊 shutil

    1.shutil模塊概述:
        1.shutil模塊擁有許多檔案,檔案夾操作的功能,包括復制,移動,重命名,洗掉,壓縮等
        2.匯入語法: import shutil

    2.檔案處理

# 將檔案內容拷貝到另一個檔案中
shutil.copyfileobj(open('old.xml', 'r'), open('new.xml', 'w'))

# 拷貝檔案
shutil.copyfile('f1.log', 'f2.log')  # 目標檔案無需存在

# 僅拷貝權限
shutil.copymode('f1.log', 'f2.log')  # 目標檔案必須存在,內容,組用戶均不變

# 僅拷貝狀態的資訊,包括: mode bits, atime, mtime, flags
shutil.copystat('f1.log', 'f2.log')  # 目標檔案必須存在

# 拷貝檔案和權限
shutil.copy('f1.log', 'f2.log')

# 拷貝檔案和狀態資訊
shutil.copy2('f1.log', 'f2.log')

    3.檔案夾處理

# 遞回的去拷貝檔案夾
# 目標目錄不能存在,注意對folder2目錄父級目錄要有可寫權限,ignore的意思是排除
shutil.copytree('folder1', 'folder2', ignore=shutil.ignore_patterns('*.pyc', 'tmp*'))
# 拷貝軟連接-通常的拷貝都把軟連接拷貝成硬鏈接,即對待軟連接來說是創建新的檔案
shutil.copytree('f1', 'f2', symlinks=True, ignore=shutil.ignore_patterns('*.pyc', 'tmp*'))

# 遞回的去洗掉檔案
shutil.rmtree('要清空的檔案夾名')

# 把一個檔案從一個檔案夾移動到另一個檔案夾,并同時重命名
shutil.move('原檔案夾/原檔案名', '目標檔案夾/目標檔案名')

    4.壓縮包處理

# 創建壓縮包并回傳檔案的路徑
shutil.make_archive(base_name, format,...)
"""引數說明
    base_name: 壓縮包的檔案名,也可以是壓縮包的路徑,只是檔案名時,則保存至當前目錄,否則保存至指定路徑
        如: data_bak                       =>保存至當前路徑
        如: /tmp/data_bak                  =>保存至/tmp/
    format: 壓縮包種類,"zip", "tar", "bztar", "gztar"
    root_dir: 要壓縮的檔案夾路徑(默認當前目錄)
    owner: 用戶,默認當前用戶
    group: 組,默認當前組
    logger: 用于記錄日志,通常是logging.Logger物件
"""

# 將 /data 下的檔案打包放置當前程式目錄
ret = shutil.make_archive("data_bak", 'gztar', root_dir='/data')

# 將 /data下的檔案打包放置 /tmp/目錄
ret = shutil.make_archive("/tmp/data_bak", 'gztar', root_dir='/data')

    5.壓縮原理: shutil 對壓縮包的處理是呼叫 ZipFile 和 TarFile 兩個模塊來進行的

        ZipFile壓縮和解壓縮

import zipfile

# 壓縮
z = zipfile.ZipFile('laxi.zip', 'w')
z.write('a.log')
z.write('data.data')
z.close()

# 解壓
z = zipfile.ZipFile('laxi.zip', 'r')
z.extractall(path='.')
z.close()

        TarFile壓縮和解壓縮

import tarfile

# 壓縮
t=tarfile.open('/tmp/egon.tar', 'w')
t.add('/test1/a.py', arcname='a.bak')
t.add('/test1/b.py', arcname='b.bak')
t.close()

# 解壓
t=tarfile.open('/tmp/egon.tar', 'r')
t.extractall('/egon')
t.close()

16.數學模塊 math

import math

# 變數
math.e              自然對數的底e
math.pi             圓周率pi

# 函式
math.ceil(x)        對x向上取整,比如x=1.2,回傳2
math.floor(x)       對x向下取整,比如x=1.2,回傳1
math.sqrt(x)        回傳x的平方根
math.factorial(x)   求x的階乘
math.log(x[, base]) 回傳以base為底x的對數, 如果不給出base,則以自然對數e為底
math.log10(x)       求以10為底x的對數
math.pow(x, y)      回傳 x**y (x的y次方)
math.fabs(x)        回傳浮點數x的絕對值

# 角度和弧度degrees互換
math.degree(x)      將弧度x轉換為角度
math.radians(x)     將角度x轉換為弧度

# 三角函式
math.sin(x)     回傳x的正弦(x為弧度)
math.cos(x)     回傳x的余弦(x為弧度)
math.tan(x)     回傳x的正切(x為弧度)
math.asin(x)    回傳x的反正弦(回傳值為為弧度)
math.acos(x)    回傳x的反余弦(回傳值為為弧度)
math.atan(x)    回傳x的反正切(回傳值為為弧度)

轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/49467.html

標籤:Python

上一篇:django基礎、環境搭建(前后端不分離)

下一篇:Django model 層之事務管理總結

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 【C++】Microsoft C++、C 和匯編程式檔案

    ......

    uj5u.com 2020-09-10 00:57:23 more
  • 例外宣告

    相比于斷言適用于排除邏輯上不可能存在的狀態,例外通常是用于邏輯上可能發生的錯誤。 例外宣告 Item 1:當函式不可能拋出例外或不能接受拋出例外時,使用noexcept 理由 如果不打算拋出例外的話,程式就會認為無法處理這種錯誤,并且應當盡早終止,如此可以有效地阻止例外的傳播與擴散。 示例 //不可 ......

    uj5u.com 2020-09-10 00:57:27 more
  • Codeforces 1400E Clear the Multiset(貪心 + 分治)

    鏈接:https://codeforces.com/problemset/problem/1400/E 來源:Codeforces 思路:給你一個陣列,現在你可以進行兩種操作,操作1:將一段沒有 0 的區間進行減一的操作,操作2:將 i 位置上的元素歸零。最終問:將這個陣列的全部元素歸零后操作的最少 ......

    uj5u.com 2020-09-10 00:57:30 more
  • UVA11610 【Reverse Prime】

    本人看到此題沒有翻譯,就附帶了一個自己的翻譯版本 思考 這一題,它的第一個要求是找出所有 $7$ 位反向質數及其質因數的個數。 我們應該需要質數篩篩選1~$10^{7}$的所有數,這里就不慢慢介紹了。但是,重讀題,我們突然發現反向質數都是 $7$ 位,而將它反過來后的數字卻是 $6$ 位數,這就說明 ......

    uj5u.com 2020-09-10 00:57:36 more
  • 統計區間素數數量

    1 #pragma GCC optimize(2) 2 #include <bits/stdc++.h> 3 using namespace std; 4 bool isprime[1000000010]; 5 vector<int> prime; 6 inline int getlist(int ......

    uj5u.com 2020-09-10 00:57:47 more
  • C/C++編程筆記:C++中的 const 變數詳解,教你正確認識const用法

    1、C中的const 1、區域const變數存放在堆疊區中,會分配記憶體(也就是說可以通過地址間接修改變數的值)。測驗代碼如下: 運行結果: 2、全域const變數存放在只讀資料段(不能通過地址修改,會發生寫入錯誤), 默認為外部聯編,可以給其他源檔案使用(需要用extern關鍵字修飾) 運行結果: ......

    uj5u.com 2020-09-10 00:58:04 more
  • 【C++犯錯記錄】VS2019 MFC添加資源不懂如何修改資源宏ID

    1. 首先在資源視圖中,添加資源 2. 點擊新添加的資源,復制自動生成的ID 3. 在解決方案資源管理器中找到Resource.h檔案,編輯,使用整個專案搜索和替換的方式快速替換 宏宣告 4. Ctrl+Shift+F 全域搜索,點擊查找全部,然后逐個替換 5. 為什么使用搜索替換而不使用屬性視窗直 ......

    uj5u.com 2020-09-10 00:59:11 more
  • 【C++犯錯記錄】VS2019 MFC不懂的批量添加資源

    1. 打開資源頭檔案Resource.h,在其中預先定義好宏 ID(不清楚其實ID值應該設定多少,可以先新建一個相同的資源項,再在這個資源的ID值的基礎上遞增即可) 2. 在資源視圖中選中專案資源,按F7編輯資源檔案,按 ID 型別 相對路徑的形式添加 資源。(別忘了先把檔案拷貝到專案中的res檔案 ......

    uj5u.com 2020-09-10 01:00:19 more
  • C/C++編程筆記:關于C++的參考型別,專供新手入門使用

    今天要講的是C++中我最喜歡的一個用法——參考,也叫別名。 參考就是給一個變數名取一個變數名,方便我們間接地使用這個變數。我們可以給一個變數創建N個參考,這N + 1個變數共享了同一塊記憶體區域。(參考型別的變數會占用記憶體空間,占用的記憶體空間的大小和指標型別的大小是相同的。雖然參考是一個物件的別名,但 ......

    uj5u.com 2020-09-10 01:00:22 more
  • 【C/C++編程筆記】從頭開始學習C ++:初學者完整指南

    眾所周知,C ++的學習曲線陡峭,但是花時間學習這種語言將為您的職業帶來奇跡,并使您與其他開發人員區分開。您會更輕松地學習新語言,形成真正的解決問題的技能,并在編程的基礎上打下堅實的基礎。 C ++將幫助您養成良好的編程習慣(即清晰一致的編碼風格,在撰寫代碼時注釋代碼,并限制類內部的可見性),并且由 ......

    uj5u.com 2020-09-10 01:00:41 more
最新发布
  • Rust中的智能指標:Box<T> Rc<T> Arc<T> Cell<T> RefCell<T> Weak

    Rust中的智能指標是什么 智能指標(smart pointers)是一類資料結構,是擁有資料所有權和額外功能的指標。是指標的進一步發展 指標(pointer)是一個包含記憶體地址的變數的通用概念。這個地址參考,或 ” 指向”(points at)一些其 他資料 。參考以 & 符號為標志并借用了他們所 ......

    uj5u.com 2023-04-20 07:24:10 more
  • Java的值傳遞和參考傳遞

    值傳遞不會改變本身,參考傳遞(如果傳遞的值需要實體化到堆里)如果發生修改了會改變本身。 1.基本資料型別都是值傳遞 package com.example.basic; public class Test { public static void main(String[] args) { int ......

    uj5u.com 2023-04-20 07:24:04 more
  • [2]SpinalHDL教程——Scala簡單入門

    第一個 Scala 程式 shell里面輸入 $ scala scala> 1 + 1 res0: Int = 2 scala> println("Hello World!") Hello World! 檔案形式 object HelloWorld { /* 這是我的第一個 Scala 程式 * 以 ......

    uj5u.com 2023-04-20 07:23:58 more
  • 理解函式指標和回呼函式

    理解 函式指標 指向函式的指標。比如: 理解函式指標的偽代碼 void (*p)(int type, char *data); // 定義一個函式指標p void func(int type, char *data); // 宣告一個函式func p = func; // 將指標p指向函式func ......

    uj5u.com 2023-04-20 07:23:52 more
  • Django筆記二十五之資料庫函式之日期函式

    本文首發于公眾號:Hunter后端 原文鏈接:Django筆記二十五之資料庫函式之日期函式 日期函式主要介紹兩個大類,Extract() 和 Trunc() Extract() 函式作用是提取日期,比如我們可以提取一個日期欄位的年份,月份,日等資料 Trunc() 的作用則是截取,比如 2022-0 ......

    uj5u.com 2023-04-20 07:23:45 more
  • 一天吃透JVM面試八股文

    什么是JVM? JVM,全稱Java Virtual Machine(Java虛擬機),是通過在實際的計算機上仿真模擬各種計算機功能來實作的。由一套位元組碼指令集、一組暫存器、一個堆疊、一個垃圾回收堆和一個存盤方法域等組成。JVM屏蔽了與作業系統平臺相關的資訊,使得Java程式只需要生成在Java虛擬機 ......

    uj5u.com 2023-04-20 07:23:31 more
  • 使用Java接入小程式訂閱訊息!

    更新完微信服務號的模板訊息之后,我又趕緊把微信小程式的訂閱訊息給實作了!之前我一直以為微信小程式也是要企業才能申請,沒想到小程式個人就能申請。 訊息推送平臺🔥推送下發【郵件】【短信】【微信服務號】【微信小程式】【企業微信】【釘釘】等訊息型別。 https://gitee.com/zhongfuch ......

    uj5u.com 2023-04-20 07:22:59 more
  • java -- 緩沖流、轉換流、序列化流

    緩沖流 緩沖流, 也叫高效流, 按照資料型別分類: 位元組緩沖流:BufferedInputStream,BufferedOutputStream 字符緩沖流:BufferedReader,BufferedWriter 緩沖流的基本原理,是在創建流物件時,會創建一個內置的默認大小的緩沖區陣列,通過緩沖 ......

    uj5u.com 2023-04-20 07:22:49 more
  • Java-SpringBoot-Range請求頭設定實作視頻分段傳輸

    老實說,人太懶了,現在基本都不喜歡寫筆記了,但是網上有關Range請求頭的文章都太水了 下面是抄的一段StackOverflow的代碼...自己大修改過的,寫的注釋挺全的,應該直接看得懂,就不解釋了 寫的不好...只是希望能給視頻網站開發的新手一點點幫助吧. 業務場景:視頻分段傳輸、視頻多段傳輸(理 ......

    uj5u.com 2023-04-20 07:22:42 more
  • Windows 10開發教程_編程入門自學教程_菜鳥教程-免費教程分享

    教程簡介 Windows 10開發入門教程 - 從簡單的步驟了解Windows 10開發,從基本到高級概念,包括簡介,UWP,第一個應用程式,商店,XAML控制元件,資料系結,XAML性能,自適應設計,自適應UI,自適應代碼,檔案管理,SQLite資料庫,應用程式到應用程式通信,應用程式本地化,應用程式 ......

    uj5u.com 2023-04-20 07:22:35 more