模塊:為了編寫可維護的代碼,我們將很多函數分組,分別放到不同的文件里,這樣,代碼的可利用率提高,代碼量減少。在Python中,一個 .py文件就稱之為一個模塊(module)。
模塊有以下幾種方式:
a.Python標准庫
b.第三方模塊
c.引用程序自定義模塊
引入模塊方式:
1、import 模塊名1,模塊名2(調用:模塊名1.函數名)
1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 4 5 def add(x, y): 6 return x+y 7 8 9 def sub(x, y): 10 return x-y
1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 import cal 4 5 6 print(cal.add(3, 5))
2、from 模塊名1 import 函數名(調用:函數名)
#!/usr/bin/env python # -*- coding:utf-8 -*- def add(x, y): return x+y def sub(x, y): return x-y
1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 from cal import add # 只引入一個函數 4 from cal import * # 引入多個函數 5 6 7 print(add(3, 5))
1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 import sys # 引入標准庫 4 print(sys.path) # 查看當前路徑 5 6 from my_module import cal # 引入自定義庫,在當前路徑的下一層 7 from my_module.module1.module2 import cal # 引入自定義庫,多級目錄 8 print(cal.add(3, 2))
•time模塊
在Python中,通常有這幾種方式來表示時間:
a.時間戳(timestamp):通常來說,時間戳表示的是從1970年1月1日00:00:00開始按秒計算的偏移量。我們運行“type(time.time())”,返回的是float類型
b. 格式化的時間字符串
c.元祖(struct_time):struct_time元祖共有9個元素(年,月,日,時,分,秒,一年中第幾周,一年中第幾天,夏令時)
1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 import time 4 5 # 時間戳,用於計算 6 print(time.time()) # 1548861231.773613秒,從1970年1月1日 00:00:00開始計算 7 # 結構化時間,當地時間 8 print(time.localtime()) # time.struct_time(tm_year=2019, tm_mon=1, tm_mday=30, tm_hour=23, tm_min=18, tm_sec=52, tm_wday=2, tm_yday=30, tm_isdst=0) 9 t = time.localtime() 10 print(t.tm_year) # 獲取當前年份 11 print(t.tm_mday) # 獲取當前月的第多少天 12 print(t.tm_wday) # 獲取這周第幾天,默認從0-6 13 # 結構化時間,標准時間--UTC 14 print(time.gmtime()) # 世界標准時間,英國;time.struct_time(tm_year=2019, tm_mon=1, tm_mday=30, tm_hour=15, tm_min=26, tm_sec=17, tm_wday=2, tm_yday=30, tm_isdst=0) 15 ''' 16 struct_time ---> Timestamp:mktime 17 Timestamp ---> struct_time:localtime/gmtime 18 struct_time ---> Format string:strftime 19 Format string ---> struct_time:strptime 20 strptime:把一個格式化時間字符串轉換為struct_time。實際上它和strftime()是逆操作 21 %Y:年 22 %m:月 23 %d:日 24 %X:時分秒 25 ''' 26 # ----將結構化時間轉換成時間戳 27 print(time.mktime(time.localtime())) 28 # ----將結構化時間轉成字符串時間 29 print(time.strftime("%Y-%m-%d %X", time.localtime())) 30 # ----將字符串時間轉成結構化時間 31 print(time.strptime("2019:01:30:23:53:59", "%Y:%m:%d:%X")) 32 33 print(time.asctime()) # Wed Jan 30 23:56:16 2019 34 print(time.ctime()) # Wed Jan 30 23:57:09 2019 35 ''' 36 time.sleep(3):線程推遲指定的時間運行,單位為秒 37 time.clock(): 38 a.UNIX系統上,他返回的是“進程時間”,它是用秒表示的浮點數 39 b.Windows中,第一次調用,返回的是進程運行的實際時間;第二次之后的調用時第一次調用以后到現在運行的時間,即時間差 40 ''' 41 42 43 import datetime 44 print(datetime.datetime.now()) # 2019-01-31 00:04:25.944866
•random模塊
1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 import random 4 print(random.random()) # 0-1之間的隨機數 5 print(random.randint(1, 10)) # 自定義范圍的整形 6 print(random.randrange(1, 5)) # 自定義范圍,第二個數取不到 7 print(random.choice([11, 12, 13, 14, 15])) 8 print(random.sample([11, 12, 13, 14, 15], 2)) # 指定一個列表,並指定隨機產生的個數 9 print(random.uniform(1, 3)) # 取任意范圍的float 10 item = [1, 3, 5, 7, 9] 11 random.shuffle(item) # 打亂集合中的順序 12 print(item)

1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 import random 4 5 6 def v_code(): 7 res = "" 8 for i in range(5): 9 num = random.randint(0, 9) 10 alf = chr(random.randint(65, 122)) 11 s = str(random.choice([num, alf])) 12 res += s 13 return res 14 15 16 print(v_code()) # 25Ze5
•OS模塊
OS模塊是與操作系統交互的一個接口
1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 import os 4 print(os.getcwd()) # 獲取當前工作目錄,即當前python腳本工作的目錄路徑 5 # print(os.chdir("dirname")) # 改變當前腳本工作目錄,相當於shell下cd 6 print(os.curdir) # 返回當前目錄:('.') 7 print(os.pardir) # 獲取當前目錄的父目錄字符串名:('..') 8 print(os.makedirs('dirname1/dirname2')) # 可生成多層遞歸目錄 9 print(os.removedirs('dirname')) # 若目錄為空,則刪除,並遞歸到上一級目錄,如若也為空,則刪除,以此類推 10 print(os.mkdir('dirname')) # 生成單級目錄,相當於shell中 mkdir dirname 11 print(os.rmdir('dirname')) # 刪除單級空目錄,若目錄不為空則無法刪除,報錯;相當於shell中rmdir dirname 12 print(os.listdir('dirname')) # 列出指定目錄下的所有文件和子目錄,包括隱藏文件,並以列表方式打印 13 print(os.remove('dirname')) # 刪除一個文件 14 print(os.rename('oldname', 'newname')) # 重命名文件/目錄 15 print(os.stat('path/filename')) # 獲取文件/目錄信息 16 print(os.sep) # 輸出操作系統特定的路徑分隔符,win下為'\\',linux下為'\' 17 print(os.linesep) # 輸出當前平台使用的行終止符,win下為'\r\n',linux下為'\n' 18 print(os.pathsep) # 輸出用於分割文件路徑的字符串win下為';',linux下為': ' 19 print(os.name) # 輸出字符串指定當前使用平台。win下為'nt',linux下為'posix' 20 print(os.system('bash command')) # 運行shell命令,直接顯示 21 print(os.environ) # 獲取系統環境變量 22 print(os.path.abspath('path')) # 返回path規范化的絕對路徑 23 print(os.path.split('path')) # 將path分割成目錄和文件名二元祖返回 24 print(os.path.dirname('path')) # 返回path目錄,其實就是os.path.split('path') 的第一個元素 25 print(os.path.basename('path')) # 返回path最后的文件名。 26 print(os.path.exists('path')) # 如果path存在,返回True;反之則False 27 print(os.path.isabs('path')) # 如果path是絕對路徑,返回True 28 print(os.path.isdir('path')) # 如果path是一個存在的目錄,則返回True,反之則False 29 print(os.path.join('path1', 'path2')) # 將多個路徑組合后返回,第一個絕對路徑之前的參數將被忽略 30 print(os.path.getatime('path')) # 返回path所指向的文件或目錄的最后存取時間 31 print(os.path.getmtime('path')) # 返回path所指向的文件或目錄的最后修改時間
•sys模塊
1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 import sys 4 print(sys.argv) # 命令行參數list,第一個元素是程序本身路徑 5 print(sys.exit('n')) # 退出程序,正常退出時exit(0) 6 print(sys.version) # 獲取Python解釋程序的版本信息 7 print(sys.path) # 返回模塊的搜索路徑,初始化時使用Pythonpath環境變量的值 8 print(sys.platform) # 返回操作系統平台名稱

1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 import sys,time 4 for i in range(100): 5 sys.stdout.write('#') 6 time.sleep(0.1) # 睡眠0.1秒 7 sys.stdout.flush() # 刷新緩存
•json & pickle 模塊
之前學習過的Python內置函數eval方法可以將一個字符串轉成python對象,不過,eval方法是有局限性的,對於普通的數據類型,json.loads和eval都能用,但遇到特殊類型的時候,eval就不管用了,所以eval的重點還是通常用來執行一個字符串表達式,並返回表達式的值。
1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 import json 4 # x = "[null,true,false,1]" 5 # # print(eval(x)) # 報錯 6 # print(json.loads(x)) # [None, True, False, 1] 7 dic = {"name": "alex"} 8 f = open("hello", "w") 9 dic_str = json.dumps(dic) 10 f.write(dic_str) # 等價於 json.dump(dic,f),一般用於文件操作
1 # import pickle 2 # dic = {'name': 'alex', 'age': 23, 'sex': 'male'} 3 # print(type(dic)) # <class 'dict'> 4 # j = pickle.dumps(dic) 5 # print(type(j)) # <class 'bytes'> 6 # f = open('序列化對象_pickle', 'wb') # 注意是w是寫入str,wb是寫入bytes,j是'bytes' 7 # f.write(j) # 等價於 pickle.dump(dic,j) 8 # f.close() 9 10 # -------反序列化 11 import pickle 12 f = open('序列化對象_pickle', 'rb') 13 data = pickle.loads(f.read()) # 等價於 data = pickle.load(f) 14 print(data['name'])
什么是序列化?
我們把對象(變量)從內存中編程可存儲或傳輸的過程稱之為序列化,在Python中叫pickling,在其他語言中也被稱為serialization,marshalling,flattening等等,都是一個意思。
序列化之后,就可以把序列化后的內存寫入磁盤,或者通過網絡傳輸到別的機器上。
反過來,把變量內存從序列化的對象重新讀到內存里稱之為反序列化,即unpickling。
json
如果我們要在不同的編程語言之間傳遞對象,就必須把對象序列化為標准格式,比如XML,但更好的方法是序列化未JSON,因為JSON表示出來就是一個字符串,可以被所有語言讀取,也可以方便地存儲到磁盤或者通過網絡傳輸。JSON不僅是標准格式,並且比XML更快,而且可以直接在Web頁面中讀取,非常方便。
•XML模塊
XML是實現不同語言或程序之間進行數據交換的協議,跟json差不多,但json使用起來更簡單,不過,以前在json還沒誕生的黑暗年代,大家只能選擇用XML呀,至今很多傳統公司如金融行業的很多系統的接口還主要是XML。
XML的格式如下,就是通過<>節點來區別數據結構的:

1 <?xml version ="1.0" ?> 2 <date> 3 <country name="Liechtenstein"> 4 <rank updated="yes">2</rank> 5 <year>2008</year> 6 <gdppc>141100</gdppc> 7 <neighbor name="Austria" direction="E"/> 8 <neighbor name="Switzerland" direction="W"/> 9 </country> 10 </date>
XML協議在各個語言里的都是支持的,在Python中可以用以下模塊操作xml:
1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 import xml.etree.ElementTree as ET 4 5 tree = ET.parse("xml_lesson") # 調用ET下的parse解析這個XML文件,拿到的對象賦值給tree 6 root = tree.getroot() 7 print(root.tag) 8 9 # 遍歷XML文檔 10 for child in root: 11 print(child.tag, child.attrib) # child.attrib:獲取節點屬性 12 for i in child: 13 print(i.tag, i.attrib, i.text) 14 15 # 只遍歷year節點 16 for node in root.iter('rank'): # 遍歷root根節點下的iter某一節點的“rank” 17 print(node.tag, node.text) 18 19 # 修改 20 for node_update in root.iter('rank'): 21 new_rank = int(node_update.text) + 1 22 node_update.text = str(new_rank) 23 node_update.set('updated', 'no') # 設置他的標簽值 24 25 tree.write('xml_lesson') # 將內存中的數據重新寫入進去 26 27 # 刪除node 28 for country in root.findall('country'): 29 rank = int(country.find('rank').text) 30 if rank == 5: 31 root.remove(country) 32 33 tree.write('xml_lesson')

1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 import xml.etree.ElementTree as ET 4 new_xml = ET.Element("namelist") # 創建根節點 5 name = ET.SubElement(new_xml, "name", attrib={"enrooled": "yes"}) 6 age = ET.SubElement(name, "age", attrib={"checked": "no"}) 7 sex = ET.SubElement(name, "sex") 8 sex.text = '33' 9 name2 = ET.SubElement(new_xml, "name", attrib={"enrolled": "no"}) 10 age = ET.SubElement(name2, "age") 11 age.text = '19' 12 13 et = ET.ElementTree(new_xml) # 生成文檔對象 14 et.write("xml_test.xml", encoding="utf-8", xml_declaration=True) 15 16 ET.dump(new_xml) # 打印生成的格式 17 18 # =========以下為XML創建效果===== 19 <?xml version='1.0' encoding='utf-8'?> 20 <namelist> 21 <name enrooled="yes"> 22 <age checked="no" /> 23 <sex>33</sex> 24 </name> 25 <name enrolled="no"> 26 <age>19</age> 27 </name> 28 </namelist>
•re模塊
正則表達式(或re)是一種小型的、高度專業化的編程語言,(Python)它內嵌在Python中,並通過re模塊實現。正則表達式模式被編譯成一系列的字節碼,然后由用C編寫的匹配引擎執行。
字符匹配(普通字符,元字符):
普通字符 >>>re.findall('alex', 'zhangsanalexlisi')
['alex']
元字符:.、^、$、*、+、?、{}、[]、|、()、\
.:匹配任意字符,除\n之外

1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 import re 4 print(re.findall('alex', 'zhangsanalexlisi')) # ['alex'] 5 print(re.findall('a..x', 'zhangsanalexlisi')) # ['alex']
^:必須將“^”放在字符串開頭位置,判斷字符串以XXX開頭,返回布爾值,如果以XXX開頭,返回“真”,反之則“假”

1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 import re 4 print(re.findall('^alex', 'zhangsanalexlisi')) # [] 5 print(re.findall('^alex', 'alexzhangsanlisi')) # ['alex'] 6 print(re.findall('^a..x', 'zhangsanalexlisi')) # [] 7 print(re.findall('^a..x', 'alexzhangsanlisi')) # ['alex']
$:必須將“$”放在字符串結尾位置,判斷字符串以XXX結尾,返回布爾值,如果以XXX結尾,返回“真”,反之則“假”

1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 import re 4 print(re.findall('alex$', 'zhangsanalexlisi')) # [] 5 print(re.findall('alex$', 'zhangsanlisialex')) # ['alex'] 6 print(re.findall('^alex$', 'zhangsanalexlisi')) # [] 7 print(re.findall('^alex$', 'alex')) # ['alex'] 8 print(re.findall('a..x$', 'zhangsanalexlisi')) # [] 9 print(re.findall('a..x$', 'zhangsanlisialex')) # ['alex'] 10 print(re.findall('^a..x$', 'zhangsanlisialex')) # [''] 11 print(re.findall('^a..x$', 'alex')) # ['alex']
*、+、?、{}:以x重復出現

1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 import re 4 # *:范圍(0,無窮) 5 print(re.findall('d*', 'zhangsanddddddalexlisi')) # ['', '', '', '', '', '', '', '', 'dddddd', '', '', '', '', '', '', '', '', ''] 6 7 8 # +:范圍(1,無窮) 9 print(re.findall('d+', 'zhangsanddddddalexlisi')) # ['dddddd'] 10 11 12 # *與+區別: 13 print(re.findall('alex*', 'asdfgalex')) # ['alex'] 14 print(re.findall('alex+', 'asdfgalex')) # ['alex'] 15 print(re.findall('alex*', 'asdfgale')) # ['ale'] 16 print(re.findall('alex+', 'asdfgale')) # [] 17 18 19 # ?:范圍(0,1) 20 print(re.findall('alex?', 'asdfgale')) # ['ale'] 21 print(re.findall('alex?', 'asdfgalex')) # ['alex'] 22 23 24 # *與?共用:以最小匹配0次 25 print(re.findall('alex*?', 'asdfgale')) # ['ale'] 26 print(re.findall('alex*?', 'asdfgalexxxx')) # ['ale'] 27 28 29 # +與?共用:以最小匹配1次 30 print(re.findall('alex+?', 'asdfgale')) # [] 31 print(re.findall('alex+?', 'asdfgalexxxx')) # ['alex'] 32 33 34 # {}: 給定一個范圍 35 # {0,無窮}==>* 36 # {1,無窮}==>+ 37 # {0,1} ==>? 38 # {6}:出現6次 39 # {1,6}:出現1至6任意一個次數 40 print(re.findall('alex{6}', 'asdfgalex')) # [] 41 print(re.findall('alex{6}', 'asdfgalexxxxxx')) # ['alexxxxxx'] 42 print(re.findall('alex{1,6}', 'asdfgalexxx')) # ['alexxx'] 43 print(re.findall('alex{1,6}', 'asdfgalexxxxxx')) # ['alexxxxxx']
[]:中間出現的全部為普通字符;相當於“或”;只匹配一個;表示范圍

1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 import re 4 5 # []字符串:中間出現的全部為普通字符;相當於“或”;只匹配一個;表示范圍 6 print(re.findall('x[y]', 'abcx')) # [] 7 print(re.findall('x[y]', 'abcxy')) # ['xy'] 8 9 10 # 中間出現:* 11 print(re.findall('x[y*]', 'abcx')) # [] 12 print(re.findall('x[y*]', 'abcxy')) # ['xy'] 13 print(re.findall('x[y*]', 'abcx*')) # ['x*'] 14 15 16 # 中間出現:-;范圍不允許a-Z,只能a-z或者A-Z 17 print(re.findall('a[a-z]', 'a2bcdefghijklmnopqrxtuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ')) # [] 18 print(re.findall('a[a-z]', 'abcdefghijklmnopqrxtuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ')) # ['ab'] 19 print(re.findall('a[A-Z]', 'a2bcdefghijklmnopqrxtuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ')) # [] 20 print(re.findall('a[A-Z]', 'aAbcdefghijklmnopqrxtuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ')) # ['aA'] 21 22 23 # 后面在出現一個:* 24 print(re.findall('a[a-z]*', 'a2bcdefghijklmnopqrxtuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ')) # ['a'] 25 print(re.findall('a[a-z]*', 'abcdefghijklmnopqrxtuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ')) # ['abcdefghijklmnopqrxtuvwxyz'] 26 print(re.findall('a[a-z]*', 'abcdefghijklmnopqrxtuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ9')) # ['abcdefghijklmnopqrxtuvwxyz'] 27 28 29 # 中間出現:^;代表“非” 30 print(re.findall('q[^a-z]', 'qabc')) # [] 31 print(re.findall('q[^a-z]', 'q12')) # ['q1']
|:“或”的意思,要么左邊,要么右邊

1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 import re 4 print(re.findall(r'ka|b', 'sdfgjkabc')) # ['ka', 'b'] 5 print(re.findall(r'ka|b', 'sdfgjkac')) # ['ka'] 6 print(re.findall(r'ka|b', 'sdfgjkbc')) # ['b']
():分組,代表一個整體

1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 import re 4 print(re.findall('(abc)', 'abcabcabc')) # ['abc', 'abc', 'abc'] 5 print(re.search('\d', 'dfas25fd35')) # <re.Match object; span=(4, 5), match='2'> 6 print(re.search('\d', 'dfas25fd35').group()) # 2 7 print(re.search('\d+', 'dfas25fd35')) # <re.Match object; span=(4, 6), match='25'> 8 print(re.search('\d+', 'dfas25fd35').group()) # 25 9 print(re.search('\d{3}', 'dfas25fd35')) # None 10 print(re.search('(?P<name>[a-z]+)', 'alex28liming33')) # <re.Match object; span=(0, 4), match='alex'> 11 print(re.search('(?P<name>[a-z]+)', 'alex28liming33').group()) # alex 12 print(re.search('(?P<name>[a-z]+)\d+', 'alex28liming33')) # <re.Match object; span=(0, 6), match='alex28'> 13 print(re.search('(?P<name>[a-z]+)\d+', 'alex28liming33').group()) # alex28 14 print(re.search('(?P<name>[a-z]+)\d+', 'alex28liming33').group('name')) # alex
\:轉義符
反斜杠后面跟元字符去除特殊功能
反斜杠后面跟普通字符實現特殊功能
\d:匹配任何十進制數;相當於[0-9]

1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 import re 4 print(re.findall('\d', '12+(34*6+2-5*(2-1))')) # ['1', '2', '3', '4', '6', '2', '5', '2', '1'] 5 print(re.findall('\d+', '12+(34*6+2-5*(2-1))')) # ['12', '34', '6', '2', '5', '2', '1']
\D:匹配任何非十進制數;相當於[^0-9]

1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 import re 4 print(re.findall('\D', '12+(34*6+2-5*(2-1))')) # ['+', '(', '*', '+', '-', '*', '(', '-', ')', ')'] 5 print(re.findall('\D+', '12+(34*6+2-5*(2-1))')) # ['+(', '*', '+', '-', '*(', '-', '))']
\s:匹配任何空白字符;相當於[\t\n\r\f\v]

1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 import re 4 5 # 轉義符:\ 6 print(re.findall('\s', 'hello word!')) # [' ']
\S:匹配任何非空白字符;相當於[^\t\n\r\f\v]

1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 import re 4 5 print(re.findall('\S', 'hello word!')) # ['h', 'e', 'l', 'l', 'o', 'w', 'o', 'r', 'd', '!'] 6 print(re.findall('\S+', 'hello word!')) # ['hello', 'word!']
\w:匹配任何字母數字字符;相當於[a-zA-Z0-9]
\W:匹配任何非字母數字字符;相當於[^a-zA-Z0-9]
\b:匹配任何一個特殊字符邊界,如:空格、&、#等
re模塊下的常用方法
1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 import re 4 # 1 5 print(re.findall('a', 'alex lisi')) # ['a'];返回所有滿足匹配條件的結果,放到列表里 6 7 8 # 2 9 print(re.search('a', 'alex lisi').group()) # a;函數在字符串內查找模式匹配,只能找到第一個匹配然后返回一個包;通過調用group()方法得到匹配的字符串,如果字符串沒有匹配,則返回node 10 11 12 # 3 13 print(re.match('a', 'zabc')) # None;同search(),僅匹配字符串開始處 14 15 16 # 4 17 print(re.split(' ', 'hello word abc')) # ['hello', 'word', 'abc'] 18 19 20 # 5 21 print(re.sub('\d+', 'A', 'alex6jack5', 1)) # alexAjack5 22 print(re.subn('\d+', 'A', 'alex6jack5', 1)) # ('alexAjack5', 1) 23 24 25 # 6 26 com = re.compile('\d{3}') 27 print(com.search('abc123de45').group()) # 123;可以多次調用 28 29 # 7 30 ret = re.finditer("\d+", "ab35cde47fg88") 31 print(ret) # <callable_iterator object at 0x00000028E5A765C0> 32 print(next(ret).group()) # 35 33 print(next(ret).group()) # 47 34 print(next(ret).group()) # 88
re補充:
1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 import re 4 print(re.findall('www\.(baidu|sina)\.com', 'www.baidu.com')) # ['baidu'];優先匹配分組的內容 5 6 # 分組中添加‘?:’去除優先級 7 print(re.findall('www\.(?:baidu|sina)\.com', 'www.baidu.com')) # ['www.baidu.com']
•logging模塊
一(簡單引用)
1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 import logging 4 logging.debug('debug message') 5 logging.info('info message') 6 logging.warning('warning message') # WARNING:root:warning message 7 logging.error('error message') # ERROR:root:error message 8 logging.critical('critical message') # CRITICAL:root:critical message
可見,默認情況下Python和logging模塊將日志打印到了標准輸出中,且只顯示了大於等於WARNING級別的日志,這說明默認的日志級別設置為WARNING(日志級別登記CRITICAL>ERROR>WARNING>INFO>DEBUG>NOTSET),默認的日志格式為日志級別,Logging名稱:用戶輸出消息。
二 靈活配置日志級別,日志格式,輸出位置
1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 import logging 4 5 logging.basicConfig( 6 level=logging.DEBUG, # 設置級別,大於等於當前級別的打印出來 7 filename='logger.log', # 指定存放位置,默認為追加的模式 8 filemode='w', # 設置日志的格式 9 format='%(asctime)s %(filename)s [%(lineno)d] %(message)s' 10 11 # %(asctime)s;2019-02-04 19:02:34,392 12 13 # %(asctime)s %(lineno)d 14 # 2019-02-04 19:03:03,556 15 15 # 2019-02-04 19:03:03,556 16 16 # 2019-02-04 19:03:03,556 17 17 # 2019-02-04 19:03:03,556 18 18 # 2019-02-04 19:03:03,557 19 19 20 # %(asctime)s [%(lineno)d] %(message)s 21 # 2019-02-04 19:16:13,040 [20] debug message 22 # 2019-02-04 19:16:13,040 [21] info message 23 # 2019-02-04 19:16:13,040 [22] warning message 24 # 2019-02-04 19:16:13,040 [23] error message 25 # 2019-02-04 19:16:13,040 [24] critical message 26 27 # %(asctime)s %(filename)s [%(lineno)d] %(message)s 28 # 2019-02-04 19:21:47,164 sys_logging.py [26] debug message 29 # 2019-02-04 19:21:47,165 sys_logging.py [27] info message 30 # 2019-02-04 19:21:47,165 sys_logging.py [28] warning message 31 # 2019-02-04 19:21:47,165 sys_logging.py [29] error message 32 # 2019-02-04 19:21:47,165 sys_logging.py [30] critical message 33 ) 34 35 logging.debug('debug message') 36 logging.info('info message') 37 logging.warning('warning message') # WARNING:root:warning message 38 logging.error('error message') # ERROR:root:error message 39 logging.critical('critical message') # CRITICAL:root:critical message
filemode:文件打開方式,在指定了filename時使用這個參數,默認值為‘a’還可指定為‘w’
format:指定handler使用的日志顯示格式
datefmt:指定日期時間格式
level:設置rootlogger的日志級別
stream:用指定的stream創建StreamHandler。可以指定輸出到sys.stderr/sys.stdout或者文件(f=open('test.log', 'w')),默認為sys.stderr,若同時列出了filename和stream兩個參數,則stream參數會被忽略。
format參數中可能用到的格式化串:
%(name)s:Logger的名字
%(levelno)s:數字形式的日志級別
%(levelname)s:文本形式的日志級別
%(pathname)s:調用日志輸出函數的模塊的完整路徑名,可能沒有
%(filename)s:調用日志輸出函數的模塊的文件名
%(module)s:調用日志輸出函數的模塊名
%(funcName)s:調用日志輸出函數的函數名
%(lineno)d:調用日志輸出函數的語句所在的代碼行
%(created)f:當前時間,用UNIX標准的表示時間的浮點數表示
%(relativeCreated)d:輸出日志信息時的,自Logger創建以來的毫秒數
%(asctime)s:字符串形式的當前時間,默認格式是'2019-02-04 20:07:00,896'。逗號后面的是毫秒
%(thread)d:線程ID。可能沒有
%(threadName)s:線程名。可能沒有
%(process)d:進程ID。可能沒有
%(message)s:用戶輸出的消息
三 logger對象
上述幾個例子中我們了解了logging.debug()、logging.info()、logging.warning()、logging.error()、logging.critical()(分別用以記錄不同級別的日志信息),logging.basicConfig()(用默認日志格式(Formatter))為日志系統建立一個默認的流處理器(StreamHandler),設置基礎配置(如日志級別等)並加到(root logger(根Logger)中)這幾個logging模塊級別的函數,另外還有一個模塊級別的函數是logging.getLogger([name])(返回一個logger對象,如果沒有指定名字將返回root logger)
下面是一個最簡單的過程:
1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 import logging 4 logger = logging.getLogger() # 創建一個文件 5 6 fh = logging.FileHandler('test_log') 7 ch = logging.StreamHandler() 8 9 fm = logging.Formatter('%(asctime)s %(message)s') 10 fh.setFormatter(fm) 11 ch.setFormatter(fm) 12 13 logger.addHandler(fh) 14 logger.addHandler(ch) 15 logger.setLevel('DEBUG') 16 17 logger.debug('debug') 18 logger.info('info') 19 logger.warning('warning') # 2019-02-04 20:38:33,423 warning 20 logger.error('error') # 2019-02-04 20:38:33,423 error 21 logger.critical('critical') # 2019-02-04 20:38:33,424 critical
•configparser模塊
好多軟件的常見文檔格式如下:
1 [DEFAULT] 2 ServerAliveInterval = 45 3 Compression = yes 4 CompressionLevel = 9 5 ForwardXll = yes 6 7 [bitbucket.org] 8 User = hg 9 10 [topsecret.server.com] 11 Port = 50022 12 ForwardXll = no
如果想用Python生成一個這樣的文檔怎么做呢?
1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 import configparser 4 5 config = configparser.ConfigParser() # config = {} 一個空字典 6 config["DEFAULT"] = { 7 'ServerAliveInterval': '45', 8 'Compression': 'yes', 9 'CompressionLevel': '9' 10 } 11 12 config['bitbucket.org'] = {} 13 config['bitbucket.org']['user'] = 'hg' 14 config['topsecret.server.com'] = {} 15 topsecret = config['topsecret.server.com'] 16 topsecret['Host Port'] = '50022' # mutates the parser 17 topsecret['ForwardXll'] = 'no' # same here 18 # config['DEFAULT']['ForwardXll'] = 'yes' 19 with open('example.ini', 'w') as f: 20 config.write(f)

1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 import configparser 4 config = configparser.ConfigParser() 5 6 # ----查詢---- 7 print(config.sections()) # [] 8 config.read('example.ini') # 讀文件 9 print(config.sections()) # ['bitbucket.org', 'topsecret.server.com'] 10 print(config['bitbucket.org']['User']) # hg 11 12 for key in config['bitbucket.org']: 13 print(key) 14 # 打印結果 15 # user 16 # serveraliveinterval 17 # compression 18 # compressionlevel 19 # forwardxll 20 21 print(config.options('bitbucket.org')) # ['user', 'serveraliveinterval', 'compression', 'compressionlevel', 'forwardxll'] 22 print(config.items('bitbucket.org')) # [('serveraliveinterval', '45'), ('compression', 'yes'), ('compressionlevel', '9'), ('forwardxll', 'yes'), ('user', 'hg')] 23 print(config.get('bitbucket.org', 'compression')) # yes;獲取鍵值對中的值 24 25 # ----刪、改、增:config.write(open('i.cfg', 'w'))---- 26 config.add_section('user_name') # 新增一個塊 27 config.set('user_name', 'user', 'test') # 給新增塊,添加鍵值對 28 config.remove_section('user_nsmr') # 刪除塊 29 config.remove_option('topsecret.server.com', 'forwardxll') # 刪除塊的,鍵值對 30 config.write(open('i.cfg', 'w'))
•hashlib模塊
用於加密相關的操作,3.x里代替了md5模塊和sha模塊,主要提供SHA1,SHA224,SHA256,SHA384,SHA512,MD5算法
1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 import hashlib 4 obj = hashlib.md5() # m = hashlib.sha256() 5 obj.update("hello".encode('utf8')) 6 print(obj.hexdigest()) # 5d41402abc4b2a76b9719d911017c592
以上加密算法雖然依然非常厲害,但是存在缺陷,即:通過撞庫可以反解。所以,有必要對加密算法中添加自定義key再來加密。
1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 import hashlib 4 hash = hashlib.sha256('alex'.encode('utf8')) 5 hash.update('admin'.encode('utf8')) 6 print(hash.hexdigest()) # dee0368f9334b2fd79fa8a37305064025be9ae0ddc8860c0f886b519867c2875
Python還有一個hmac模塊,它內部對我們創建key和內容,再進行處理然后再加密:
1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 import hmac 4 h = hmac.new('alex'.encode('utf8')) 5 h.update('hello'.encode('utf8')) 6 print(h.hexdigest()) # c28dbb0cd8e52d54fdcbbff08a5d2dc0