模塊,用一坨代碼實現了某個功能的代碼集合。html
相似於函數式編程和麪向過程變成,函數式編程則完成一個功能,其餘代碼用來調用便可,提供了代碼的重用性和代碼間的耦合。而對於一個複雜的功能,可能須要多個函數才成完成(函數又能夠在不一樣的.py文件中),n個.py文件組成的代碼集合就成爲模塊。node
如: os是系統相關的模塊,file是文件操做相關的模塊python
模塊分爲三種:git
自定義模塊和開源模塊的使用參考 http://www.cnblogs.com/wupeiqi/articles/4963027.html 正則表達式
時間相關操做,時間有三種表示方式:算法
import time # print(time.clock()) #返回處理器時間,3.3開始已廢棄 , 改爲了time.process_time()測量處理器運算時間,不包括sleep時間,不穩定,mac上測不出來 # print(time.altzone) #返回與utc時間的時間差,以秒計算\ # print(time.asctime()) #返回時間格式"Fri Aug 19 11:14:16 2016", # print(time.localtime()) #返回本地時間 的struct time對象格式 # print(time.gmtime(time.time()-800000)) #返回utc時間的struc時間對象格式 # print(time.asctime(time.localtime())) #返回時間格式"Fri Aug 19 11:14:16 2016", #print(time.ctime()) #返回Fri Aug 19 12:38:29 2016 格式, 同上 # 日期字符串 轉成 時間戳 # string_2_struct = time.strptime("2016/05/22","%Y/%m/%d") #將 日期字符串 轉成 struct時間對象格式 # print(string_2_struct) # # # struct_2_stamp = time.mktime(string_2_struct) #將struct時間對象轉成時間戳 # print(struct_2_stamp) #將時間戳轉爲字符串格式 # print(time.gmtime(time.time()-86640)) #將utc時間戳轉換成struct_time格式 # print(time.strftime("%Y-%m-%d %H:%M:%S",time.gmtime()) ) #將utc struct_time格式轉成指定的字符串格式 #時間加減 import datetime # print(datetime.datetime.now()) #返回 2016-08-19 12:47:03.941925 #print(datetime.date.fromtimestamp(time.time()) ) # 時間戳直接轉成日期格式 2016-08-19 # print(datetime.datetime.now() ) # print(datetime.datetime.now() + datetime.timedelta(3)) #當前時間+3天 # print(datetime.datetime.now() + datetime.timedelta(-3)) #當前時間-3天 # print(datetime.datetime.now() + datetime.timedelta(hours=3)) #當前時間+3小時 # print(datetime.datetime.now() + datetime.timedelta(minutes=30)) #當前時間+30分 # # c_time = datetime.datetime.now() # print(c_time.replace(minute=3,hour=2)) #時間替換
隨機數shell
mport random print random.random() print random.randint(1,2) print random.randrange(1,10)
生成隨機驗證碼編程
import random checkcode = '' for i in range(4): current = random.randrange(0,4) if current != i: temp = chr(random.randint(65,90)) else: temp = random.randint(0,9) checkcode += str(temp) print checkcode
提供對操做系統進行調用的接口json
os.getcwd() 獲取當前工做目錄,即當前python腳本工做的目錄路徑 os.chdir("dirname") 改變當前腳本工做目錄;至關於shell下cd os.curdir 返回當前目錄: ('.') os.pardir 獲取當前目錄的父目錄字符串名:('..') os.makedirs('dirname1/dirname2') 可生成多層遞歸目錄 os.removedirs('dirname1') 若目錄爲空,則刪除,並遞歸到上一級目錄,如若也爲空,則刪除,依此類推 os.mkdir('dirname') 生成單級目錄;至關於shell中mkdir dirname os.rmdir('dirname') 刪除單級空目錄,若目錄不爲空則沒法刪除,報錯;至關於shell中rmdir dirname os.listdir('dirname') 列出指定目錄下的全部文件和子目錄,包括隱藏文件,並以列表方式打印 os.remove() 刪除一個文件 os.rename("oldname","newname") 重命名文件/目錄 os.stat('path/filename') 獲取文件/目錄信息 os.sep 輸出操做系統特定的路徑分隔符,win下爲"\\",Linux下爲"/" os.linesep 輸出當前平臺使用的行終止符,win下爲"\r\n",Linux下爲"\n" os.pathsep 輸出用於分割文件路徑的字符串 os.name 輸出字符串指示當前使用平臺。win->'nt'; Linux->'posix' os.system("bash command") 運行shell命令,直接顯示 os.environ 獲取系統環境變量 os.path.abspath(path) 返回path規範化的絕對路徑 os.path.split(path) 將path分割成目錄和文件名二元組返回 os.path.dirname(path) 返回path的目錄。其實就是os.path.split(path)的第一個元素 os.path.basename(path) 返回path最後的文件名。如何path以/或\結尾,那麼就會返回空值。即os.path.split(path)的第二個元素 os.path.exists(path) 若是path存在,返回True;若是path不存在,返回False os.path.isabs(path) 若是path是絕對路徑,返回True os.path.isfile(path) 若是path是一個存在的文件,返回True。不然返回False os.path.isdir(path) 若是path是一個存在的目錄,則返回True。不然返回False os.path.join(path1[, path2[, ...]]) 將多個路徑組合後返回,第一個絕對路徑以前的參數將被忽略 os.path.getatime(path) 返回path所指向的文件或者目錄的最後存取時間 os.path.getmtime(path) 返回path所指向的文件或者目錄的最後修改時間
更多猛擊這裏windows
用於提供對解釋器相關的操做
sys.argv 命令行參數List,第一個元素是程序自己路徑 sys.exit(n) 退出程序,正常退出時exit(0) sys.version 獲取Python解釋程序的版本信息 sys.maxint 最大的Int值 sys.path 返回模塊的搜索路徑,初始化時使用PYTHONPATH環境變量的值 sys.platform 返回操做系統平臺名稱 sys.stdout.write('please:') val = sys.stdin.readline()[:-1]
更多猛擊這裏
高級的文件,文件夾,壓縮包 處理模塊
1. shutil.copyfileobj(fsrc,fdst)
把一個文件的內容拷貝到另外一個文件中,能夠部份內容
with open("f_old",'r',encoding="utf-8") as f1,\ open("f_new","w",encoding="utf-8") as f2: shutil.copyfileobj(f1,f2) #拷貝文件的內容
2. shutil.copyfile(src,dst)
拷貝文件,可是不拷貝全部權限
shutil.copyfile("f_old","f_new") #同一目錄下拷貝文件 shutil.copyfile(r'D:\PycharmProjects\pyhomework\day5\shutil_mode\shutil_mod\f_old',r'd:\f_new') #經過絕對路徑拷貝文件
3. shutil.copymode(src,dst)
僅拷貝權限。內容、組、用戶均不變
[root@whtest137 ~]# ll total 8 -rwxr-xr-x 1 root root 0 Apr 1 16:05 zhangqigao #有執行權限 -rw-r--r-- 1 whtest whtest 0 Apr 1 16:06 zhangqigao_old #沒有執行權限 >>> import os,shutil >>> os.chdir("/root") #拷貝"zhangqigao_old"權限給"zhangqigao" >>> shutil.copymode("zhangqigao_old","zhangqigao") [root@whtest137 ~]# ll total 8 -rw-r--r-- 1 root root 0 Apr 1 16:05 zhangqigao # 得到跟"zhangqigao_old"同樣的文件權限 -rw-r--r-- 1 whtest whtest 0 Apr 1 16:06 zhangqigao_old
4.shutil.copystat(src,dst)
拷貝文件的狀態信息,如:mode bits, atime, mtime, flags
#兩個文件的建立時間和用戶權限都不一樣 [root@jenkins_sh temp]# ll total 0 -rw-r--r-- 1 root root 0 Apr 1 17:31 zhangqigao -rwxr-xr-x 1 jenkins jenkins 0 Apr 1 16:26 zhangqigao_old #python操做 >>> import os,shutil >>> os.chdir("/temp") #zhangqigao 這個文件狀態 >>> os.stat("zhangqigao") posix.stat_result(st_mode=33188, st_ino=76808194, st_dev=2053L, st_nlink=1, st_uid=0, st_gid=0, st_size=0, st_atime=1491039109, st_mtime=1491039109, st_ctime=1491039109) #zhangqigao_old的文件狀態 >>> os.stat("zhangqigao_old") posix.stat_result(st_mode=33261, st_ino=76808195, st_dev=2053L, st_nlink=1, st_uid=101, st_gid=103, st_size=0, st_atime=1491035188, st_mtime=1491035188, st_ctime=1491035242) #拷貝zhangqigao_old 文件狀態給zhangqigao 文件 >>> shutil.copystat("zhangqigao_old","zhangqigao") # 拷貝後,zhangqigao文件的文件狀態 >>> os.stat("zhangqigao") posix.stat_result(st_mode=33261, st_ino=76808194, st_dev=2053L, st_nlink=1, st_uid=0, st_gid=0, st_size=0, st_atime=1491035188, st_mtime=1491035188, st_ctime=1491039237) #操做後兩個文件比較 [root@jenkins_sh temp]# ll total 0 -rwxr-xr-x 1 root root 0 Apr 1 16:26 zhangqigao #狀態包括文件權限,文件建立的時間等,不包括文件所屬用戶和用戶組 -rwxr-xr-x 1 jenkins jenkins 0 Apr 1 16:26 zhangqigao_old
5. shutil.copy(src,dst)
拷貝文件和權限
#拷貝前 [root@jenkins_sh temp]# ll total 0 -rwxr-xr-x 1 jenkins jenkins 0 Apr 1 16:26 zhangqigao_old #拷貝中 >>> import os,shutil >>> os.chdir("/temp") >>> shutil.copy("zhangqigao_old","zhangqigao") #拷貝結果輸出 [root@jenkins_sh temp]# ll total 0 -rwxr-xr-x 1 root root 0 Apr 1 17:42 zhangqigao #拷貝了zhangqigao_old文件和文件權限 -rwxr-xr-x 1 jenkins jenkins 0 Apr 1 16:26 zhangqigao_old
6. shutil.copy2(src,dst)
拷貝文件和狀態信息
#拷貝前 [root@jenkins_sh temp]# ll total 0 -rwxr-xr-x 1 jenkins jenkins 0 Apr 1 16:26 zhangqigao_old #拷貝中 >>> import os,shutil >>> os.chdir("/temp") >>> shutil.copy2("zhangqigao_old","zhangqigao") #拷貝後 [root@jenkins_sh temp]# ll total 0 -rwxr-xr-x 1 root root 0 Apr 1 16:26 zhangqigao #拷貝了zhangqigao_old的文件和狀態 -rwxr-xr-x 1 jenkins jenkins 0 Apr 1 16:26 zhangqigao_old
7. shutil.copytree(src,dst)
遞歸去拷貝文件,至關於cp -r
#操做前 [root@jenkins_sh temp]# ll total 4 drwxr-xr-x 2 root root 4096 Apr 1 17:53 xiaogao [root@jenkins_sh temp]# cd xiaogao/;ll total 0 -rwxr-xr-x 1 root root 0 Apr 1 16:26 zhangqigao -rwxr-xr-x 1 jenkins jenkins 0 Apr 1 16:26 zhangqigao_old #操做中 >>> import os,shutil >>> os.chdir("/temp") >>> shutil.copytree("xiaogao","gaogao") #遞歸拷貝 #操做結果 [root@jenkins_sh temp]# ll total 8 drwxr-xr-x 2 root root 4096 Apr 1 17:53 gaogao #拷貝成功 drwxr-xr-x 2 root root 4096 Apr 1 17:53 xiaogao [root@jenkins_sh temp]# cd gaogao/;ll total 0 -rwxr-xr-x 1 root root 0 Apr 1 16:26 zhangqigao -rwxr-xr-x 1 root root 0 Apr 1 16:26 zhangqigao_old
8. shutil.rmtree(path[,ignore_errors[,onerror]])
遞歸去刪除文件,至關於rm -rf
#操做前 [root@jenkins_sh temp]# ll total 4 drwxr-xr-x 2 root root 4096 Apr 1 17:53 xiaogao [root@jenkins_sh temp]# cd xiaogao/;ll total 0 -rwxr-xr-x 1 root root 0 Apr 1 16:26 zhangqigao -rwxr-xr-x 1 jenkins jenkins 0 Apr 1 16:26 zhangqigao_old #操做中 >>> import os,shutil >>> os.chdir("/temp") >>> shutil.rmtree("xiaogao") #操做結果 [root@jenkins_sh temp]# ll total 0 #成功刪除xiaogao目錄
9. shutil.move(src,dst)
遞歸的去移動文件,至關於mv
#操做前 [root@jenkins_sh temp]# ll total 4 drwxr-xr-x 2 root root 4096 Apr 1 18:07 xiaogao -rw-r--r-- 1 root root 0 Apr 1 18:07 zhangqigao #操做中 >>> import shutil >>> shutil.move("/temp/zhangqigao","/temp/xiaogao") #把文件移到目錄中 #操做結果 [root@jenkins_sh xiaogao]# ll total 4 drwxr-xr-x 2 root root 4096 Apr 1 18:08 xiaogao [root@jenkins_sh temp]# cd xiaogao/;ll total 0 -rw-r--r-- 1 root root 0 Apr 1 18:07 zhangqigao
10.shutil.make_archive((base_name, format, root_dir=None,base_dir=None,verbose=0,dry=0,owner=None,group=None,logger=None)
建立壓縮包並返回文件路徑,例如:zip、tar
#將 /Users/wupeiqi/Downloads/test 下的文件打包放置當前程序目錄 import shutil ret = shutil.make_archive("wwwwwwwwww", 'gztar', root_dir='/Users/wupeiqi/Downloads/test') #將 /Users/wupeiqi/Downloads/test 下的文件打包放置 /Users/wupeiqi/目錄 import shutil ret = shutil.make_archive("/Users/wupeiqi/wwwwwwwwww", 'gztar', root_dir='/Users/wupeiqi/Downloads/test')
11. zipfile
以zip的形式壓縮文件,注意了這個只能壓縮文件,不能壓縮目錄,若是壓縮,也只能顯示空目錄。
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() #解壓 z.close()
12. tarfile
以tar的形式打包文件,這邊能打包全部文件,包括目錄
import tarfile # 打包 tar = tarfile.open('your.tar','w') #不加arcname打的是絕對路徑,也就是/Users/wupeiqi/PycharmProjects/bbs2.zip,加這個表示你在your.tar中加什麼文件就寫什麼文件名,也就是bbs2.zip tar.add('/Users/wupeiqi/PycharmProjects/bbs2.zip', arcname='bbs2.zip') tar.add('/Users/wupeiqi/PycharmProjects/cmdb.zip', arcname='cmdb.zip') tar.close() # 解壓 tar = tarfile.open('your.tar','r') tar.extractall() # 可設置解壓地址 tar.close()
參考:http://www.cnblogs.com/wupeiqi/articles/4963027.html
用於序列化的兩個模塊
Json模塊提供了四個功能:dumps, dump, loads, load
pickle模塊提供了四個功能:dumps, dump, loads, load
使用方法參考:這裏
shelve模塊是一個簡單的k,v將內存數據經過文件持久化的模塊,能夠持久化任何pickle可支持的python數據格式
import shelve d = shelve.open('shelve_test') #打開一個文件 class Test(object): def __init__(self,n): self.n = n t = Test(123) t2 = Test(123334) name = ["alex","rain","test"] d["test"] = name #持久化列表 d["t1"] = t #持久化類 d["t2"] = t2 d.close()
詳細使用方法實例:http://www.cnblogs.com/zhangqigao/articles/6672235.html
xml是實現不一樣語言或程序之間進行數據交換的協議,跟json差很少,但json使用起來更簡單,不過,古時候,在json還沒誕生的黑暗年代,你們只能選擇用xml呀,至今不少傳統公司如金融行業的不少系統的接口還主要是xml。
xml的格式以下,就是經過<>節點來區別數據結構的:
<?xml version="1.0"?> <data> <country name="Liechtenstein"> <rank updated="yes">2</rank> <year>2008</year> <gdppc>141100</gdppc> <neighbor name="Austria" direction="E"/> <neighbor name="Switzerland" direction="W"/> </country> <country name="Singapore"> <rank updated="yes">5</rank> <year>2011</year> <gdppc>59900</gdppc> <neighbor name="Malaysia" direction="N"/> </country> <country name="Panama"> <rank updated="yes">69</rank> <year>2011</year> <gdppc>13600</gdppc> <neighbor name="Costa Rica" direction="W"/> <neighbor name="Colombia" direction="E"/> </country> </data>
xml協議在各個語言裏的都 是支持的,在python中能夠用如下模塊操做xml
import xml.etree.ElementTree as ET tree = ET.parse("xmltest.xml") root = tree.getroot() print(root.tag) #遍歷xml文檔 for child in root: print(child.tag, child.attrib) for i in child: print(i.tag,i.text) #只遍歷year 節點 for node in root.iter('year'): print(node.tag,node.text)
修改和刪除xml文檔內容
import xml.etree.ElementTree as ET tree = ET.parse("xmltest.xml") root = tree.getroot() #修改 for node in root.iter('year'): new_year = int(node.text) + 1 node.text = str(new_year) node.set("updated","yes") tree.write("xmltest.xml") #刪除node for country in root.findall('country'): rank = int(country.find('rank').text) if rank > 50: root.remove(country) tree.write('output.xml')
本身建立xml文檔
import xml.etree.ElementTree as ET new_xml = ET.Element("namelist") name = ET.SubElement(new_xml,"name",attrib={"enrolled":"yes"}) age = ET.SubElement(name,"age",attrib={"checked":"no"}) sex = ET.SubElement(name,"sex") sex.text = '33' name2 = ET.SubElement(new_xml,"name",attrib={"enrolled":"no"}) age = ET.SubElement(name2,"age") age.text = '19' et = ET.ElementTree(new_xml) #生成文檔對象 et.write("test.xml", encoding="utf-8",xml_declaration=True) ET.dump(new_xml) #打印生成的格式
ConfigParser模塊
用於生成和修改常見配置文檔,當前模塊的名稱在python3.x版本中變動爲configparser
文檔格式以下
[DEFAULT] ServerAliveInterval = 45 Compression = yes CompressionLevel = 9 ForwardX11 = yes [bitbucket.org] User = hg [topsecret.server.com] Port = 50022 ForwardX11 = no
若是想用python生成一個這樣的文檔怎麼作呢?
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)
寫完了還能夠再讀出來
>>> import configparser >>> config = configparser.ConfigParser() >>> config.sections() [] >>> config.read('example.ini') ['example.ini'] >>> config.sections() ['bitbucket.org', 'topsecret.server.com'] >>> 'bitbucket.org' in config True >>> 'bytebong.com' in config False >>> config['bitbucket.org']['User'] 'hg' >>> config['DEFAULT']['Compression'] 'yes' >>> topsecret = config['topsecret.server.com'] >>> topsecret['ForwardX11'] 'no' >>> topsecret['Port'] '50022' >>> for key in config['bitbucket.org']: print(key) ... user compressionlevel serveraliveinterval compression forwardx11 >>> config['bitbucket.org']['ForwardX11'] 'yes'
configparser增刪改查語法
[section1] k1 = v1 k2:v2 [section2] k1 = v1 import ConfigParser config = ConfigParser.ConfigParser() config.read('i.cfg') # ########## 讀 ########## #secs = config.sections() #print secs #options = config.options('group2') #print options #item_list = config.items('group2') #print item_list #val = config.get('group1','key') #val = config.getint('group1','key') # ########## 改寫 ########## #sec = config.remove_section('group1') #config.write(open('i.cfg', "w")) #sec = config.has_section('wupeiqi') #sec = config.add_section('wupeiqi') #config.write(open('i.cfg', "w")) #config.set('group2','k1',11111) #config.write(open('i.cfg', "w")) #config.remove_option('group2','age') #config.write(open('i.cfg', "w"))
用於加密相關的操做,3.x裏代替了md5模塊和sha模塊,主要提供SHA1, SHA224, SHA256, SHA384, SHA512, MD5算法
import hashlib m = hashlib.md5() m.update(b"Hello") m.update(b"It's me") print(m.digest()) m.update(b"It's been a long time since last time we ...") print(m.digest()) #2進制格式hash print(len(m.hexdigest())) #16進制格式hash ''' def digest(self, *args, **kwargs): # real signature unknown """ Return the digest value as a string of binary data. """ pass def hexdigest(self, *args, **kwargs): # real signature unknown """ Return the digest value as a string of hexadecimal digits. """ pass ''' import hashlib # ######## md5 ######## hash = hashlib.md5() hash.update('admin') print(hash.hexdigest()) # ######## sha1 ######## hash = hashlib.sha1() hash.update('admin') print(hash.hexdigest()) # ######## sha256 ######## hash = hashlib.sha256() hash.update('admin') print(hash.hexdigest()) # ######## sha384 ######## hash = hashlib.sha384() hash.update('admin') print(hash.hexdigest()) # ######## sha512 ######## hash = hashlib.sha512() hash.update('admin') print(hash.hexdigest())
python 還有一個 hmac 模塊,它內部對咱們建立 key 和 內容 再進行處理而後再加密
散列消息鑑別碼,簡稱HMAC,是一種基於消息鑑別碼MAC(Message Authentication Code)的鑑別機制。使用HMAC時,消息通信的雙方,經過驗證消息中加入的鑑別密鑰K來鑑別消息的真僞;
通常用於網絡通訊中消息加密,前提是雙方先要約定好key,就像接頭暗號同樣,而後消息發送把用key把消息加密,接收方用key + 消息明文再加密,拿加密後的值 跟 發送者的相對比是否相等,這樣就能驗證消息的真實性,及發送者的合法性了。
import hmac h = hmac.new(b'天王蓋地虎', b'寶塔鎮河妖') print h.hexdigest()
更多關於md5,sha1,sha256等介紹的文章看這裏https://www.tbs-certificates.co.uk/FAQ/en/sha256.html
在沒有subprocess這個模塊的時候,經過os.system(),os.popen(),commands這三個模塊和操做系統作交互
1. os.system()
做用:執行操做系統命令,只返回命令的執行狀態(0:成功,非0:失敗),不返回命令的執行結果
>>> import os >>> os.system("ls -l") total 16708 -rw-------. 1 root root 1350 Jan 4 01:51 anaconda-ks.cfg -rw-r--r--. 1 root root 8017 Jan 4 01:51 install.log 0 #執行返回的狀態 >>> res = os.system("ls -l") total 16708 -rw-------. 1 root root 1350 Jan 4 01:51 anaconda-ks.cfg -rw-r--r--. 1 root root 8017 Jan 4 01:51 install.log >>> res 0 #0: 表示成功 >>> res = os.system("lm") sh: lm: command not found >>> res 32512 #非0:表示失敗
2. os.popen()
做用:執行操做系統命令,不返回命令的執行狀態,只返回命令的執行結果。
>>> import os >>> os.popen("ls -l") <open file 'ls -l', mode 'r' at 0x7f5ded070540> >>> res = os.popen("ls -l") >>> a = res.read() >>> print(a) #打印返回結果 total 16708 -rw-------. 1 root root 1350 Jan 4 01:51 anaconda-ks.cfg -rw-r--r--. 1 root root 8017 Jan 4 01:51 install.log
注:執行popen() 不是直接返回命令的執行結果的,而是須要read一下,這是由於popen至關於打開了一個文件,它把結果存到文件中,只不過它是至關於存在內存中了,可是你好像打開文件的樣子去取同樣。
3. commands模塊
做用:便可以獲取命令的執行狀態,也能夠獲取命令的執行結果,可是隻能在python2.7有這個命令,在python3.5以後就沒有,還有就是這個模塊只支持Linux, Windows不支持,這裏知道這個命令就好了。
>>> import commands #導入commands命令 >>> commands.getstatusoutput("ls -l") (0, 'total 16708\n-rw-------. 1 root root 1350 Jan 4 01:51 anaconda-ks.cfg\n -rw-r--r--. 1 root root 8017 Jan 4 01:51 install.log') #元組的形式返回 >>> res = commands.getstatusoutput("ls -l") >>> res[0] #執行狀態 0 >>> print(res[1]) #執行結果 total 16708 -rw-------. 1 root root 1350 Jan 4 01:51 anaconda-ks.cfg -rw-r--r--. 1 root root 8017 Jan 4 01:51 install.log
上面說的commands模塊在python3.5之後的版本就沒有了,並且它又不支持windows,因此python3.5以後又出來新的模塊更爲強大,subprocess模塊
1. subprocess.run()
做用: 運行命令,返回命令的執行結果(Python3.5之後的版本纔會有這個命令)
>>> import subprocess # python 解析則傳入命令的每一個參數的列表 >>> subprocess.run(["df","-h"]) Filesystem Size Used Avail Use% Mounted on /dev/mapper/VolGroup-LogVol00 289G 70G 204G 26% / tmpfs 64G 0 64G 0% /dev/shm /dev/sda1 283M 27M 241M 11% /boot CompletedProcess(args=['df', '-h'], returncode=0) # 須要交給Linux shell本身解析,則:傳入命令字符串,shell=True >>> subprocess.run("df -h|grep /dev/sda1",shell=True) /dev/sda1 283M 27M 241M 11% /boot CompletedProcess(args='df -h|grep /dev/sda1', returncode=0)
注:執行的命令須要讓python去解釋執行這個命令,執行的命令以及參數,須要以列表的形式傳入。第二種狀況:可是若是須要交給Linux shell環境去解析的還,這傳入命令的字符串,而且聲明shell=True便可
2. subprocess.call()
做用:執行命令,返回命令的狀態,0或者非0
>>> import subprocess >>> res = subprocess.call(["ls","-l"]) total 26976 -rw-r--r-- 1 1000 1000 10914 Jan 17 15:57 aclocal.m4 drwxr-xr-x 5 root root 4096 May 12 14:21 build -rwxr-xr-x 1 1000 1000 43940 Jan 17 15:57 config.guess >>> res #返回命令的狀態 0
3. subprocess.check_call()
做用:執行命令,若是執行結果爲0,正常返回,不然拋出異常
>>> import subprocess >>> res = subprocess.check_call(["ls","-l"]) total 26976 -rw-r--r-- 1 1000 1000 10914 Jan 17 15:57 aclocal.m4 drwxr-xr-x 5 root root 4096 May 12 14:21 build >>> res 0
4. subprocess.getstatusoutput()
做用: 接受字符串形式的命令,返回元組形式,第一個元素是執行狀態,第二個是命令結果
>>> import subprocess >>> subprocess.getstatusoutput('ls /bin/ls') (0, '/bin/ls') #0:執行狀態,'bin/ls':執行結果
5. subprocess.getoutput()
做用: 接受字符串形式的命令,而且返回命令的結果
>>> import subprocess >>> subprocess.getoutput('ls /bin/ls') '/bin/ls' #返回命令的結果
6. subprocess.check_output()
做用: 執行命令,而且返回結果,不是打印
>>> import subprocess >>> res = subprocess.check_output(["ls","-l"]) >>> res b'total 26976\n-rw-r--r-- 1 1000 1000 10914 Jan 17 15:57 aclocal.m4\n drwxr-xr-x 5 root root 4096 May 12 14:21 build\n -rwxr-xr-x 1 1000 1000 43940 Jan 17 15:57 config.guess\n -rw-r--r-- 1 root root 756903 May 12 14:18 config.log\n' #這邊是以字節類型返回的
不少程序都有記錄日誌的需求,而且日誌中包含的信息即有正常的程序訪問日誌,還可能有錯誤,警告等信息輸出,python的logging模塊提供了標準的日誌接口,你能夠經過它存儲各類格式的日誌,logging的日誌能夠分爲debug,info,warning,error和critical 5個級別,下面咱們看看這個日誌模塊logging怎麼用
一. 簡單用法
說明:日誌級別有五個,分別是,debug, info ,warning, error 和critical ,其中debug級別最低,critical級別最高,級別越低,打印的日誌越多
import logging logging.debug("logging debug") logging.info("logging info") logging.warning("user [abc] attempted wrong password more than 3 times") logging.error("logging error") logging.critical("logging critical") #輸出 WARNING:root:user [abc] attempted wrong password more than 3 times ERROR:root:logging error CRITICAL:root:logging critical
1.1. 日誌級別
看一下這幾個日誌級別分別表明什麼意思
Level | When it’s used |
---|---|
DEBUG |
Detailed information, typically of interest only when diagnosing problems. |
INFO |
Confirmation that things are working as expected. |
WARNING |
An indication that something unexpected happened, or indicative of some problem in the near future (e.g. ‘disk space low’). The software is still working as expected. |
ERROR |
Due to a more serious problem, the software has not been able to perform some function. |
CRITICAL |
A serious error, indicating that the program itself may be unable to continue running. |
1.2. 日誌寫入文件
import logging logging.basicConfig(filename="catalina.log",level=logging.INFO) #輸入文件名,和日誌級別 #---日誌輸出--- logging.debug("logging debug") logging.info("logging info") logging.warning("logging warning") #輸出到文件中的內容 INFO:root:logging info WARNING:root:logging warning
注: 這句中的level=loggin.INFO意思是,把日誌紀錄級別設置爲INFO,也就是說,只有比日誌是INFO或比INFO級別更高的日誌纔會被紀錄到文件裏,因此debug日誌沒有記錄,若是想記錄,則級別設置成debug也就是level=loggin.DEBUG
1.3. 加入日期格式
logging.basicConfig(filename="catalina.log", level=logging.INFO, format='%(asctime)s %(module)s:%(levelname)s %(message)s', #格式請見第5點內容 datefmt='%m/%d/%Y %H:%M:%S %p') #須要加上format和datefmt #----日誌內容----- logging.debug("logging debug") logging.info("logging info") logging.warning("logging warning") #文件輸出 04/11/2017 14:20:22 PM logging_mod:INFO logging info 04/11/2017 14:20:22 PM logging_mod:WARNING logging warning
1.4. 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 |
字符串形式的當前時間。默認格式是 「2003-07-08 16:49:45,896」。逗號後面的是毫秒 |
%(thread)d |
線程ID。可能沒有 |
%(threadName)s |
線程名。可能沒有 |
%(process)d |
進程ID。可能沒有 |
%(message)s |
用戶輸出的 |
二. 複雜日誌輸出
以前的寫法感受要麼就輸入在屏幕上,要麼就是輸入在日誌裏面,那咱們有沒有既能夠輸出在日誌上,又輸出在日誌裏面呢?很明顯,固然能夠。下面咱們就來討論一下,如何使用複雜的日誌輸出。
1 簡介
python使用logging模塊記錄日誌涉及的四個主要類:
①logger:提供了應用程序能夠直接使用的接口。
②handler:將(logger建立的)日誌記錄發送到合適的目的輸出。
③filter:提供了細度設備來決定輸出哪條日誌記錄。
④formatter:決定日誌記錄的最終輸出格式。
2 logger
①每一個程序在輸出信息以前都須要得到一個logger。logger一般對應了程序的模塊名,好比聊天工具的圖形界面模塊能夠這樣得到它的logger:
logger = logging.getLogger("chat.gui")
核心模塊能夠這樣寫:
logger = logging.getLogger("chat.kernel")
②logger.setLevel(lel)
說明:指定最低的日誌級別,低於lel的級別將被忽略(debug是最低的內置級別,critical爲最高)
logger.setLevel(logging.DEBUG) #設置級別爲debug級別
③Logger.addFilter(filt)、Logger.removeFilter(filt)
說明:添加或刪除指定的filter
④logger.addHandler(hdlr)、logger.removeHandler(hdlr)
說明:增長或刪除指定的handler
logger.addHandler(ch)#添加handler logger.removeHandler(ch) #刪除handler
⑤Logger.debug()、Logger.info()、Logger.warning()、Logger.error()、Logger.critical()
說明:能夠設置的日誌級別
logger.debug('debug message') logger.info('info message') logger.warn('warn message') logger.error('error message') logger.critical('critical message')
⑤獲取handler個數
handler_len = len(logger.handlers) print(handler_len) #輸出 1
三、hander
handler對象負責發送相關的信息到指定目的地。Python的日誌系統有多種Handler可使用。有些Handler能夠把信息輸出到控制檯,有些Logger能夠把信息輸出到文件,還有些 Handler能夠把信息發送到網絡上。若是以爲不夠用,還能夠編寫本身的Handler。能夠經過addHandler()方法添加多個多handler 。
①Handler.setLevel(lel)
說明:指定被處理的信息級別,低於lel級別的信息將被忽略。
ch = logging.StreamHandler() ch.setLevel(logging.DEBUG)
②Handler.setFormatter()
說明:給這個handler選擇一個格式
ch_formatter = logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s") #生成格式 ch.setFormatter(ch_formatter) #設置格式
③Handler.addFilter(filt)、Handler.removeFilter(filt)
說明:新增或刪除一個filter對象
三. handler詳解
一、logging.StreamHandler
說明:使用這個Handler能夠向相似與sys.stdout或者sys.stderr的任何文件對象(file object)輸出信息,也就是屏幕輸出。
它的構造函數是:StreamHandler([strm]),其中strm參數是一個文件對象,默認是sys.stderr。
import logging logger = logging.getLogger("TEST-LOG") logger.setLevel(logging.DEBUG) ch = logging.StreamHandler() #建立一個StreamHandler對象 ch.setLevel(logging.DEBUG) #設置輸出StreamHandler日誌級別 ch_formatter = logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s") ch.setFormatter(ch_formatter) #設置時間格式 logger.addHandler(ch) # 'application' code logger.debug('debug message') logger.info('info message') logger.warn('warn message') logger.error('error message') logger.critical('critical message') #輸出 2017-04-11 16:42:49,764 - TEST-LOG - DEBUG - debug message 2017-04-11 16:42:49,764 - TEST-LOG - INFO - info message 2017-04-11 16:42:49,764 - TEST-LOG - WARNING - warn message 2017-04-11 16:42:49,765 - TEST-LOG - ERROR - error message 2017-04-11 16:42:49,765 - TEST-LOG - CRITICAL - critical message
二、logging.FileHandler
說明:和StreamHandler相似,用於向一個文件輸出日誌信息,不過FileHandler會幫你打開這個文件。
它的構造函數是:FileHandler(filename[,mode])。filename是文件名,必須指定一個文件名。mode是文件的打開方式。參見Python內置函數open()的用法。默認是’a',即添加到文件末尾。
import logging #create logging logger = logging.getLogger("TEST-LOG") logger.setLevel(logging.DEBUG) fh = logging.FileHandler("debug.log",encoding="utf-8") #日誌輸出到debug.log文件中 fh.setLevel(logging.INFO) #設置FileHandler日誌級別 fh_formatter = logging.Formatter("%(asctime)s %(module)s:%(levelname)s %(message)s") fh.setFormatter(fh_formatter) logger.addHandler(fh) # 'application' code logger.info('info message') logger.warn('warn message') logger.error('error message') logger.critical('critical message') #輸出到文件中 2017-04-11 17:09:50,035 logging_screen_output:INFO info message 2017-04-11 17:09:50,035 logging_screen_output:WARNING warn message 2017-04-11 17:09:50,035 logging_screen_output:ERROR error message 2017-04-11 17:09:50,035 logging_screen_output:CRITICAL critical message
三、logging.handlers.RotatingFileHandler
說明:這個Handler相似於上面的FileHandler,可是它能夠管理文件大小。當文件達到必定大小以後,它會自動將當前日誌文件更名,而後建立 一個新的同名日誌文件繼續輸出。好比日誌文件是chat.log。當chat.log達到指定的大小以後,RotatingFileHandler自動把 文件更名爲chat.log.1。不過,若是chat.log.1已經存在,會先把chat.log.1重命名爲chat.log.2。。。最後從新建立 chat.log,繼續輸出日誌信息。
它的構造函數是:RotatingFileHandler( filename[, mode[, maxBytes[, backupCount]]]),其中filename和mode兩個參數和FileHandler同樣。
maxBytes用於指定日誌文件的最大文件大小。若是maxBytes爲0,意味着日誌文件能夠無限大,這時上面描述的重命名過程就不會發生。
backupCount用於指定保留的備份文件的個數。好比,若是指定爲2,當上面描述的重命名過程發生時,原有的chat.log.2並不會被改名,而是被刪除。
import logging from logging import handlers #須要導入handlers logger = logging.getLogger(__name__) log_file = "timelog.log" #按文件大小來分割,10個字節,保留個數是3個 fh = handlers.RotatingFileHandler(filename=log_file,maxBytes=10,backupCount=3) formatter = logging.Formatter('%(asctime)s %(module)s:%(lineno)d %(message)s') fh.setFormatter(formatter) logger.addHandler(fh) logger.warning("test1") logger.warning("test12") logger.warning("test13") logger.warning("test14")
四、logging.handlers.TimedRotatingFileHandler
說明:這個Handler和RotatingFileHandler相似,不過,它沒有經過判斷文件大小來決定什麼時候從新建立日誌文件,而是間隔必定時間就 自動建立新的日誌文件。重命名的過程與RotatingFileHandler相似,不過新的文件不是附加數字,而是當前時間。
它的構造函數是:TimedRotatingFileHandler( filename [,when [,interval [,backupCount]]]),其中filename參數和backupCount參數和RotatingFileHandler具備相同的意義。
interval是時間間隔。when參數是一個字符串。表示時間間隔的單位,不區分大小寫。它有如下取值:①S:秒②M:分③H:小時④D:天⑤W :每星期(interval==0時表明星期一)⑥midnight:天天凌晨
import logging from logging import handlers import time logger = logging.getLogger(__name__) log_file = "timelog.log" #按時間來分割文件,按5秒一次分割,保留日誌個數是3個 fh = handlers.TimedRotatingFileHandler(filename=log_file,when="S",interval=5,backupCount=3) formatter = logging.Formatter('%(asctime)s %(module)s:%(lineno)d %(message)s') fh.setFormatter(formatter) logger.addHandler(fh) logger.warning("test1") time.sleep(2) logger.warning("test12") time.sleep(2) logger.warning("test13") time.sleep(2) logger.warning("test14") logger.warning("test15")
四. 控制檯和文件日誌共同輸出
須要什麼樣的輸出,只須要添加相應的handler就ok了
一、邏輯圖
2. 代碼以下:
import logging #create logging logger = logging.getLogger("TEST-LOG") logger.setLevel(logging.DEBUG) #屏幕handler ch = logging.StreamHandler() ch.setLevel(logging.DEBUG) #文件handler fh = logging.FileHandler("debug.log",encoding="utf-8") fh.setLevel(logging.INFO) #分別建立輸出日誌格式 ch_formatter = logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s") fh_formatter = logging.Formatter("%(asctime)s %(module)s:%(levelname)s %(message)s") #設置handler的輸出格式 ch.setFormatter(ch_formatter) fh.setFormatter(fh_formatter) #添加handler logger.addHandler(ch) logger.addHandler(fh) # 'application' code logger.debug('debug message') logger.info('info message') logger.warn('warn message') logger.error('error message') logger.critical('critical message')
注:若是添加時間分割或者文件大小分割,再添加handler便可。添加方式請見第三節中的三、4點
經常使用正則表達式符號
'.' 默認匹配除\n以外的任意一個字符,若指定flag DOTALL,則匹配任意字符,包括換行 '^' 匹配字符開頭,若指定flags MULTILINE,這種也能夠匹配上(r"^a","\nabc\neee",flags=re.MULTILINE) '$' 匹配字符結尾,或e.search("foo$","bfoo\nsdfsf",flags=re.MULTILINE).group()也能夠 '*' 匹配*號前的字符0次或屢次,re.findall("ab*","cabb3abcbbac") 結果爲['abb', 'ab', 'a'] '+' 匹配前一個字符1次或屢次,re.findall("ab+","ab+cd+abb+bba") 結果['ab', 'abb'] '?' 匹配前一個字符1次或0次 '{m}' 匹配前一個字符m次 '{n,m}' 匹配前一個字符n到m次,re.findall("ab{1,3}","abb abc abbcbbb") 結果'abb', 'ab', 'abb'] '|' 匹配|左或|右的字符,re.search("abc|ABC","ABCBabcCD").group() 結果'ABC' '(...)' 分組匹配,re.search("(abc){2}a(123|456)c", "abcabca456c").group() 結果 abcabca456c '\' 轉義 [a-z] 匹配[a-z] [A-Z] 匹配[A-Z] [0-9] 匹配數字0-9 '\A' 只從字符開頭匹配,re.search("\Aabc","alexabc") 是匹配不到的 '\Z' 匹配字符結尾,同$ '\d' 匹配數字0-9 '\D' 匹配非數字 '\w' 匹配[A-Za-z0-9] '\W' 匹配非[A-Za-z0-9] 's' 匹配空白字符、\t、\n、\r , re.search("\s+","ab\tc1\n3").group() 結果 '\t' '(?P<name>...)' 分組匹配 re.search("(?P<province>[0-9]{4})(?P<city>[0-9]{2})(?P<birthday>[0-9]{4})","371481199306143242").groupdict("city") 結果:{'province': '3714', 'city': '81', 'birthday': '1993'}
1、 經常使用匹配方法
re.match 從頭開始匹配 re.search 匹配包含 re.findall 把全部匹配到的字符放到以列表中的元素返回 re.split 以匹配到的字符當作列表分隔符 re.sub 匹配字符並替換
一、re.match(pattern, string, flags=0)
說明:在string的開始處匹配模式
>>> import re >>> a = re.match('in',"inet addr:10.161.146.134") #從頭開始匹配in字符 >>> a.group() 'in' >>> a = re.match('addr',"inet addr:10.161.146.134") #開頭匹配不到,因此返回none >>> print(a) None
二、re.search(pattern, string, flags=0)
說明:在string中尋找模式
>>> import re >>> a = re.search('addr',"inet addr:10.161.146.134") #在字符串中尋找 >>> a.group() 'addr'
三、re.findall(pattern, string, flags=0)
說明:把匹配到的字符以列表的形式返回
>>> import re >>> re.findall('[0-9]{1,3}',"inet addri:10.161.146.134") ['10', '161', '146', '134'] #符合條件的以列表的形式返回
四、re.split(pattern, string, maxsplit=0, flags=0)
說明:匹配到的字符被當作列表分割符
>>> import re >>> re.split('\.',"inet addri:10.161.146.134") ['inet addri:10', '161', '146', '134']
五、re.sub(pattern, repl, string, count=0, flags=0)
說明:匹配字符並替換
>>> import re >>> re.sub('\.','-',"inet addri:10.161.146.134") 'inet addri:10-161-146-134' #默認所有替換 >>> re.sub('\.','-',"inet addri:10.161.146.134",count=2) 'inet addri:10-161-146.134' #用count控制替換次數
六、finditer(pattern, string)
說明:返回迭代器
>>> import re >>> re.finditer('addr',"inet addr:10.161.146.134") <callable_iterator object at 0x00000000030C4BE0> #返回一個迭代器
2、經常使用方法
一、group([group1, ...])
說明:得到一個或多個分組截獲的字符串;指定多個參數時將以元組形式返回。group1可使用編號也可使用別名;編號0表明整個匹配的子串;不填寫參數時,返回group(0);沒有截獲字符串的組返回None;截獲了屢次的組返回最後一次截獲的子串。
>>> import re >>> a = re.search('addr',"inet addr:10.161.146.134") >>> a.group() 'addr' >>> a.group(0) 'addr'
二、groups(default=None)
說明:以元組形式返回所有分組截獲的字符串。至關於調用group(1,2,…last)。default表示沒有截獲字符串的組以這個值替代,默認爲None。這個要跟分組匹配結合起來使用'(...)'
>>> import re >>> a = re.search("(\d{2})(\d{2})(\d{2})(\d{4})","320922199508083319") #一個小括號表示一個組,有4個括號,就是4個組 >>> a.groups() ('32', '09', '22', '1995')
三、groupdict(default=None)
說明:返回以有別名的組的別名爲鍵、以該組截獲的子串爲值的字典,沒有別名的組不包含在內。default含義同上。這個是跟另一個分組匹配結合起來用的,即:'(?P<name>...)'
>>> import re >>> a = re.search("(?P<province>[0-9]{4})(?P<city>[0-9]{2})(?P<birthday>[0-9]{4})","371481199306143242") #如下兩種狀況獲取的值都是同樣的 >>> a.groupdict() {'birthday': '1993', 'city': '81', 'province': '3714'} >>> a.groupdict("city") {'birthday': '1993', 'city': '81', 'province': '3714'}
四、span([group])
說明:返回(start(group), end(group))
>>> import re >>> a = re.search('addr',"inet addr:10.161.146.134") >>> a.group() 'addr' >>> a.span() #獲取'addr'在字符串中的開始位置和結束位置 (5, 9)
五、start([group])
說明:返回指定的組截獲的子串在string中的起始索引(子串第一個字符的索引),group默認值爲0。
>>> import re >>> a = re.search('addr',"inet addr:10.161.146.134") >>> a.group() 'addr' >>> a.span() (5, 9) >>> a.start() #獲取字符串的起始索引 5
六、end([group])
說明:返回指定的組截獲的子串在string中的結束索引(子串最後一個字符的索引+1),group默認值爲0。
>>> import re >>> a = re.search('addr',"inet addr:10.161.146.134") >>> a.group() 'addr' >>> a.span() (5, 9) >>> a.end() #獲取string中的結束索引 9
七、compile(pattern[, flags])
說明:根據包含正則表達式的字符串建立模式對象
>>> import re >>> m = re.compile("addr") #建立正則模式對象 >>> n = m.search("inet addr:10.161.146.134") #經過模式對象去匹配 >>> n.group() 'addr'
3、反斜槓的困擾
與大多數編程語言相同,正則表達式裏使用"\"做爲轉義字符,這就可能形成反斜槓困擾。假如你須要匹配文本中的字符"\",那麼使用編程語言表示的正則表達式裏將須要4個反斜槓"\\\\":前兩個和後兩個分別用於在編程語言裏轉義成反斜槓,轉換成兩個反斜槓後再在正則表達式裏轉義成一個反斜槓。Python裏的原生字符串很好地解決了這個問題,這個例子中的正則表達式可使用r"\\"表示。一樣,匹配一個數字的"\\d"能夠寫成r"\d"。有了原生字符串,你不再用擔憂是否是漏寫了反斜槓,寫出來的表達式也更直觀。
>>> import re >>> a = re.split("\\\\","C:\ \zhangqigao\yhd_settings") >>> a ['C:', ' ', 'zhangqigao', 'yhd_settings'] >>> re.findall('\\','abc\com') Traceback (most recent call last) >>> re.findall('\\\\','abc\com') ['\\'] >>> re.findall(r'\\','abc\com') ['\\']
4、其餘匹配模式
一、re.I(re.IGNORECASE
)
說明:忽略大小寫(括號內是完整的寫法,下同)
>>> import re >>> a = re.search('addr',"inet Addr:10.161.146.134",flags=re.I) >>> a.group() 'Addr' #忽略大小寫
二、re.M(MULTILINE
)
說明:多行模式,改變'^'和'$'的行爲,詳細請見第2點
>>> import re >>> a = re.search('^a',"inet\naddr:10.161.146.134",flags=re.M) >>> a.group() 'a'
三、re.S(DOTALL
)
說明:點任意匹配模式,改變'.'的行爲
>>> import re >>> a = re.search('.+',"inet\naddr:10.161.146.134",flags=re.S) >>> a.group() 'inet\naddr:10.161.146.134'