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
