OS 模塊
#os模塊就是對操做系統進行操做,使用該模塊必須先導入模塊: import os #getcwd() 獲取當前工做目錄(當前工做目錄默認都是當前文件所在的文件夾) result = os.getcwd() print(result) #chdir()改變當前工做目錄 os.chdir('/home/sy') result = os.getcwd() print(result) open('02.txt','w') #操做時若是書寫完整的路徑則不須要考慮默認工做目錄的問題,按照實際書寫路徑操做 open('/home/sy/下載/02.txt','w') #listdir() 獲取指定文件夾中全部內容的名稱列表 result = os.listdir('/home/sy') print(result) #mkdir() 建立文件夾 #os.mkdir('girls') #os.mkdir('boys',0o777) #makedirs() 遞歸建立文件夾 #os.makedirs('/home/sy/a/b/c/d') #rmdir() 刪除空目錄 #os.rmdir('girls') #removedirs 遞歸刪除文件夾 必須都是空目錄 #os.removedirs('/home/sy/a/b/c/d') #rename() 文件或文件夾重命名 #os.rename('/home/sy/a','/home/sy/alibaba' #os.rename('02.txt','002.txt') #stat() 獲取文件或者文件夾的信息 #result = os.stat('/home/sy/PycharmProject/Python3/10.27/01.py) #print(result) #system() 執行系統命令(危險函數) #result = os.system('ls -al') #獲取隱藏文件 #print(result) #環境變量 ''' 環境變量就是一些命令的集合 操做系統的環境變量就是操做系統在執行系統命令時搜索命令的目錄的集合 ''' #getenv() 獲取系統的環境變量 result = os.getenv('PATH') print(result.split(':')) #putenv() 將一個目錄添加到環境變量中(臨時增長僅對當前腳本有效) #os.putenv('PATH','/home/sy/下載') #os.system('syls') #exit() 退出終端的命令 #os模塊中的經常使用值 #curdir 表示當前文件夾 .表示當前文件夾 通常狀況下能夠省略 print(os.curdir) #pardir 表示上一層文件夾 ..表示上一層文件夾 不可省略! print(os.pardir) #os.mkdir('../../../man')#相對路徑 從當前目錄開始查找 #os.mkdir('/home/sy/man1')#絕對路徑 從根目錄開始查找 #name 獲取表明操做系統的名稱字符串 print(os.name) #posix -> linux或者unix系統 nt -> window系統 #sep 獲取系統路徑間隔符號 window ->\ linux ->/ print(os.sep) #extsep 獲取文件名稱和後綴之間的間隔符號 window & linux -> . print(os.extsep) #linesep 獲取操做系統的換行符號 window -> \r\n linux/unix -> \n print(repr(os.linesep)) #導入os模塊 import os #如下內容都是os.path子模塊中的內容 #abspath() 將相對路徑轉化爲絕對路徑 path = './boys'#相對 result = os.path.abspath(path) print(result) #dirname() 獲取完整路徑當中的目錄部分 & basename()獲取完整路徑當中的主體部分 path = '/home/sy/boys' result = os.path.dirname(path) print(result) result = os.path.basename(path) print(result) #split() 將一個完整的路徑切割成目錄部分和主體部分 path = '/home/sy/boys' result = os.path.split(path) print(result) #join() 將2個路徑合併成一個 var1 = '/home/sy' var2 = '000.py' result = os.path.join(var1,var2) print(result) #splitext() 將一個路徑切割成文件後綴和其餘兩個部分,主要用於獲取文件的後綴 path = '/home/sy/000.py' result = os.path.splitext(path) print(result) #getsize() 獲取文件的大小 #path = '/home/sy/000.py' #result = os.path.getsize(path) #print(result) #isfile() 檢測是不是文件 path = '/home/sy/000.py' result = os.path.isfile(path) print(result) #isdir() 檢測是不是文件夾 result = os.path.isdir(path) print(result) #islink() 檢測是不是連接 path = '/initrd.img.old' result = os.path.islink(path) print(result) #getctime() 獲取文件的建立時間 get create time #getmtime() 獲取文件的修改時間 get modify time #getatime() 獲取文件的訪問時間 get active time import time filepath = '/home/sy/下載/chls' result = os.path.getctime(filepath) print(time.ctime(result)) result = os.path.getmtime(filepath) print(time.ctime(result)) result = os.path.getatime(filepath) print(time.ctime(result)) #exists() 檢測某個路徑是否真實存在 filepath = '/home/sy/下載/chls' result = os.path.exists(filepath) print(result) #isabs() 檢測一個路徑是不是絕對路徑 path = '/boys' result = os.path.isabs(path) print(result) #samefile() 檢測2個路徑是不是同一個文件 path1 = '/home/sy/下載/001' path2 = '../../../下載/001' result = os.path.samefile(path1,path2) print(result) #os.environ 用於獲取和設置系統環境變量的內置值 import os #獲取系統環境變量 getenv() 效果 print(os.environ['PATH']) #設置系統環境變量 putenv() os.environ['PATH'] += ':/home/sy/下載' os.system('chls')
os 經常使用方法css
os.remove(‘path/filename’) 刪除文件html
os.rename(oldname, newname) 重命名文件node
os.walk() 生成目錄樹下的全部文件名python
os.chdir('dirname') 改變目錄linux
os.mkdir/makedirs('dirname')建立目錄/多層目錄git
os.rmdir/removedirs('dirname') 刪除目錄/多層目錄github
os.listdir('dirname') 列出指定目錄的文件web
os.getcwd() 取得當前工做目錄算法
os.chmod() 改變目錄權限sql
os.path.basename(‘path/filename’) 去掉目錄路徑,返回文件名
os.path.dirname(‘path/filename’) 去掉文件名,返回目錄路徑
os.path.join(path1[,path2[,...]]) 將分離的各部分組合成一個路徑名
os.path.split('path') 返回( dirname(), basename())元組
os.path.splitext() 返回 (filename, extension) 元組
os.path.getatime\ctime\mtime 分別返回最近訪問、建立、修改時間
os.path.getsize() 返回文件大小
os.path.exists() 是否存在
os.path.isabs() 是否爲絕對路徑
os.path.isdir() 是否爲目錄
os.path.isfile() 是否爲文件
sys 模塊
sys.argv 命令行參數List,第一個元素是程序自己路徑
sys.modules.keys() 返回全部已經導入的模塊列表
sys.exc_info() 獲取當前正在處理的異常類,exc_type、exc_value、exc_traceback當前處理的異常詳細信息
sys.exit(n) 退出程序,正常退出時exit(0)
sys.hexversion 獲取Python解釋程序的版本值,16進制格式如:0x020403F0
sys.version 獲取Python解釋程序的版本信息
sys.maxint 最大的Int值
sys.maxunicode 最大的Unicode值
sys.modules 返回系統導入的模塊字段,key是模塊名,value是模塊
sys.path 返回模塊的搜索路徑,初始化時使用PYTHONPATH環境變量的值
sys.platform 返回操做系統平臺名稱
sys.stdout 標準輸出
sys.stdin 標準輸入
sys.stderr 錯誤輸出
sys.exc_clear() 用來清除當前線程所出現的當前的或最近的錯誤信息
sys.exec_prefix 返回平臺獨立的python文件安裝的位置
sys.byteorder 本地字節規則的指示器,big-endian平臺的值是'big',little-endian平臺的值是'little'
sys.copyright 記錄python版權相關的東西
sys.api_version 解釋器的C的API版本
sys.stdin,sys.stdout,sys.stderr
咱們經常使用print和raw_input來進行輸入和打印,那麼
print 和 raw_input是如何與標準輸入/輸出流創建關係的呢?
其實Python程序的標準輸入/輸出/出錯流定義在sys模塊中,分別 爲: sys.stdin,sys.stdout, sys.stderr
下列的程序也能夠用來輸入和輸出是同樣的:
import sys
sys.stdout.write('HelloWorld!')
print 'Please enter yourname:',
name=sys.stdin.readline()[:-1]
print 'Hi, %s!' % name
那麼sys.stdin, sys.stdout, stderr究竟是什麼呢?咱們在Python運行環境中輸入如下代碼:
import sys
for f in (sys.stdin,sys.stdout, sys.stderr): print f
輸出爲:
<open file'<stdin>', mode 'r' at 892210>
<open file'<stdout>', mode 'w' at 892270>
<open file'<stderr>', mode 'w at 8922d0>
由此能夠看出stdin, stdout, stderr在Python中無非都是文件屬性的對象,他們在Python啓動時自動與Shell 環境中的標準輸入,輸出,出錯關聯。
而Python程序的在Shell中的I/O重定向與本文開始時舉的DOS命令的重定向徹底相同,其實這種重定向是由Shell來提供的,與Python 自己並沒有關係。那麼咱們是否能夠在Python程序內部將stdin,stdout,stderr讀寫操做重定向到一個內部對象呢?答案是確定的。
Python提供了一個StringIO模塊來完成這個設想,好比:
from StringIO import StringIO
import sys
buff =StringIO()
temp =sys.stdout #保存標準I/O流
sys.stdout =buff #將標準I/O流重定向到buff對象
print 42, 'hello', 0.001
sys.stdout=temp #恢復標準I/O流
print buff.getvalue()
time模塊中時間表現的格式主要有三種:
a、timestamp時間戳,時間戳表示的是從1970年1月1日00:00:00開始按秒計算的偏移量
b、struct_time時間元組,共有九個元素組。
c、format time 格式化時間,已格式化的結構使時間更具可讀性。包括自定義格式和固定格式。
一、時間格式轉換圖:
二、主要time生成方法和time格式轉換方法實例:
#! /usr/bin/env python # -*- coding:utf-8 -*- # __author__ = "TKQ" import time # 生成timestamp time.time() # 1477471508.05
#struct_time to timestamp
time.mktime(time.localtime())
#生成struct_time # timestamp to struct_time 本地時間 time.localtime() time.localtime(time.time()) # time.struct_time(tm_year=2016, tm_mon=10, tm_mday=26, tm_hour=16, tm_min=45, tm_sec=8, tm_wday=2, tm_yday=300, tm_isdst=0) # timestamp to struct_time 格林威治時間 time.gmtime() time.gmtime(time.time()) # time.struct_time(tm_year=2016, tm_mon=10, tm_mday=26, tm_hour=8, tm_min=45, tm_sec=8, tm_wday=2, tm_yday=300, tm_isdst=0) #format_time to struct_time time.strptime('2011-05-05 16:37:06', '%Y-%m-%d %X') # time.struct_time(tm_year=2011, tm_mon=5, tm_mday=5, tm_hour=16, tm_min=37, tm_sec=6, tm_wday=3, tm_yday=125, tm_isdst=-1) #生成format_time #struct_time to format_time time.strftime("%Y-%m-%d %X") time.strftime("%Y-%m-%d %X",time.localtime()) # 2016-10-26 16:48:41 #生成固定格式的時間表示格式 time.asctime(time.localtime()) time.ctime(time.time()) # Wed Oct 26 16:45:08 2016
struct_time元組元素結構
屬性 值
tm_year(年) 好比2011
tm_mon(月) 1 - 12 tm_mday(日) 1 - 31 tm_hour(時) 0 - 23 tm_min(分) 0 - 59 tm_sec(秒) 0 - 61 tm_wday(weekday) 0 - 6(0表示週日) tm_yday(一年中的第幾天) 1 - 366 tm_isdst(是不是夏令時) 默認爲-1
format time結構化表示
格式 | 含義 |
%a | 本地(locale)簡化星期名稱 |
%A | 本地完整星期名稱 |
%b | 本地簡化月份名稱 |
%B | 本地完整月份名稱 |
%c | 本地相應的日期和時間表示 |
%d | 一個月中的第幾天(01 - 31) |
%H | 一天中的第幾個小時(24小時制,00 - 23) |
%I | 第幾個小時(12小時制,01 - 12) |
%j | 一年中的第幾天(001 - 366) |
%m | 月份(01 - 12) |
%M | 分鐘數(00 - 59) |
%p | 本地am或者pm的相應符 |
%S | 秒(01 - 61) |
%U | 一年中的星期數。(00 - 53星期天是一個星期的開始。)第一個星期天以前的全部天數都放在第0周。 |
%w | 一個星期中的第幾天(0 - 6,0是星期天) |
%W | 和%U基本相同,不一樣的是%W以星期一爲一個星期的開始。 |
%x | 本地相應日期 |
%X | 本地相應時間 |
%y | 去掉世紀的年份(00 - 99) |
%Y | 完整的年份 |
%Z | 時區的名字(若是不存在爲空字符) |
%% | ‘%’字符 |
常見結構化時間組合:
print time.strftime("%Y-%m-%d %X") #2016-10-26 20:50:13
三、time加減
#timestamp加減單位以秒爲單位 import time t1 = time.time() t2=t1+10 print time.ctime(t1)#Wed Oct 26 21:15:30 2016 print time.ctime(t2)#Wed Oct 26 21:15:40 2016
datetime模塊
datatime模塊從新封裝了time模塊,提供更多接口,提供的類有:date,time,datetime,timedelta,tzinfo。
一、date類
datetime.date(year, month, day)
靜態方法和字段
date.max、date.min:date對象所能表示的最大、最小日期;
date.resolution:date對象表示日期的最小單位。這裏是天。
date.today():返回一個表示當前本地日期的date對象;
date.fromtimestamp(timestamp):根據給定的時間戮,返回一個date對象;
方法和屬性
d1 = date(2011,06,03)#date對象 d1.year、date.month、date.day:年、月、日; d1.replace(year, month, day):生成一個新的日期對象,用參數指定的年,月,日代替原有對象中的屬性。(原有對象仍保持不變) d1.timetuple():返回日期對應的time.struct_time對象; d1.weekday():返回weekday,若是是星期一,返回0;若是是星期2,返回1,以此類推; d1.isoweekday():返回weekday,若是是星期一,返回1;若是是星期2,返回2,以此類推; d1.isocalendar():返回格式如(year,month,day)的元組; d1.isoformat():返回格式如'YYYY-MM-DD’的字符串; d1.strftime(fmt):和time模塊format相同。
二、time類
datetime.time(hour[ , minute[ , second[ , microsecond[ , tzinfo] ] ] ] )
靜態方法和字段
time.min、time.max:time類所能表示的最小、最大時間。其中,time.min = time(0, 0, 0, 0), time.max = time(23, 59, 59, 999999);
time.resolution:時間的最小單位,這裏是1微秒;
方法和屬性
t1 = datetime.time(10,23,15)#time對象
t1.hour、t1.minute、t1.second、t1.microsecond:時、分、秒、微秒;
t1.tzinfo:時區信息;
t1.replace([ hour[ , minute[ , second[ , microsecond[ , tzinfo] ] ] ] ] ):建立一個新的時間對象,用參數指定的時、分、秒、微秒代替原有對象中的屬性(原有對象仍保持不變);
t1.isoformat():返回型如"HH:MM:SS"格式的字符串表示; t1.strftime(fmt):同time模塊中的format;
三、datetime類
datetime至關於date和time結合起來。
datetime.datetime (year, month, day[ , hour[ , minute[ , second[ , microsecond[ , tzinfo] ] ] ] ] )
靜態方法和字段
datetime.today():返回一個表示當前本地時間的datetime對象;
datetime.now([tz]):返回一個表示當前本地時間的datetime對象,若是提供了參數tz,則獲取tz參數所指時區的本地時間;
datetime.utcnow():返回一個當前utc時間的datetime對象;#格林威治時間
datetime.fromtimestamp(timestamp[, tz]):根據時間戮建立一個datetime對象,參數tz指定時區信息;
datetime.utcfromtimestamp(timestamp):根據時間戮建立一個datetime對象;
datetime.combine(date, time):根據date和time,建立一個datetime對象;
datetime.strptime(date_string, format):將格式字符串轉換爲datetime對象;
方法和屬性
dt=datetime.now()#datetime對象 dt.year、month、day、hour、minute、second、microsecond、tzinfo: dt.date():獲取date對象; dt.time():獲取time對象; dt. replace ([ year[ , month[ , day[ , hour[ , minute[ , second[ , microsecond[ , tzinfo] ] ] ] ] ] ] ]): dt. timetuple () dt. utctimetuple () dt. toordinal () dt. weekday () dt. isocalendar () dt. isoformat ([ sep] ) dt. ctime ():返回一個日期時間的C格式字符串,等效於time.ctime(time.mktime(dt.timetuple())); dt. strftime (format)
4.timedelta類,時間加減
使用timedelta能夠很方便的在日期上作天days,小時hour,分鐘,秒,毫秒,微妙的時間計算,若是要計算月份則須要另外的辦法。
#coding:utf-8 from datetime import * dt = datetime.now() #日期減一天 dt1 = dt + timedelta(days=-1)#昨天 dt2 = dt - timedelta(days=1)#昨天 dt3 = dt + timedelta(days=1)#明天 delta_obj = dt3-dt print type(delta_obj),delta_obj#<type 'datetime.timedelta'> 1 day, 0:00:00 print delta_obj.days ,delta_obj.total_seconds()#1 86400.0
五、tzinfo時區類
#! /usr/bin/python # coding=utf-8 from datetime import datetime, tzinfo,timedelta """ tzinfo是關於時區信息的類 tzinfo是一個抽象類,因此不能直接被實例化 """ class UTC(tzinfo): """UTC""" def __init__(self,offset = 0): self._offset = offset def utcoffset(self, dt): return timedelta(hours=self._offset) def tzname(self, dt): return "UTC +%s" % self._offset def dst(self, dt): return timedelta(hours=self._offset) #北京時間 beijing = datetime(2011,11,11,0,0,0,tzinfo = UTC(8)) print "beijing time:",beijing #曼谷時間 bangkok = datetime(2011,11,11,0,0,0,tzinfo = UTC(7)) print "bangkok time",bangkok #北京時間轉成曼谷時間 print "beijing-time to bangkok-time:",beijing.astimezone(UTC(7)) #計算時間差時也會考慮時區的問題 timespan = beijing - bangkok print "時差:",timespan #Output================== # beijing time: 2011-11-11 00:00:00+08:00 # bangkok time 2011-11-11 00:00:00+07:00 # beijing-time to bangkok-time: 2011-11-10 23:00:00+07:00 # 時差: -1 day, 23:00:00
hashlib加密
hashlib主要提供字符加密功能,將md5和sha模塊整合到了一塊兒,支持md5,sha1, sha224, sha256, sha384, sha512等算法
具體應用
#!/usr/bin/env python # -*- coding: UTF-8 -*- #pyversion:python3.5 #owner:fuzj import hashlib # ######## md5 ######## string = "beyongjie" md5 = hashlib.md5() md5.update(string.encode('utf-8')) #注意轉碼 res = md5.hexdigest() print("md5加密結果:",res) # ######## sha1 ######## sha1 = hashlib.sha1() sha1.update(string.encode('utf-8')) res = sha1.hexdigest() print("sha1加密結果:",res) # ######## sha256 ######## sha256 = hashlib.sha256() sha256.update(string.encode('utf-8')) res = sha256.hexdigest() print("sha256加密結果:",res) # ######## sha384 ######## sha384 = hashlib.sha384() sha384.update(string.encode('utf-8')) res = sha384.hexdigest() print("sha384加密結果:",res) # ######## sha512 ######## sha512= hashlib.sha512() sha512.update(string.encode('utf-8')) res = sha512.hexdigest() print("sha512加密結果:",res)
輸出結果:
md5加密結果: 0e725e477851ff4076f774dc312d4748
sha1加密結果: 458d32be8ea38b66300174970ab0a8c0b734252f
sha256加密結果: 1e62b55bfd02977943f885f6a0998af7cc9cfb95c8ac4a9f30ecccb7c05ec9f4
sha384加密結果: e91cdf0d2570de5c96ee84e8a12cddf16508685e7a03b3e811099cfcd54b7f52183e20197cff7c07f312157f0ba4875b
sha512加密結果: 3f0020a726e9c1cb5d22290c967f3dd1bcecb409a51a8088db520750c876aaec3f17a70d7981cd575ed4b89471f743f3f24a146a39d59f215ae3e208d0170073
注意:hashlib 加密啊的字符串類型爲二進制編碼,直接加密字符串會報以下錯誤:
sha1 = hashlib.sha1()
sha1.update(string)
res = sha1.hexdigest() print("sha1加密結果:",res) TypeError: Unicode-objects must be encoded before hashing
可使用encode進行轉換
shaa1 = hashlib.sha1()
shaa1.update(string.encode('utf-8')) res = shaa1.hexdigest() print("sha1採用encode轉換加密結果:",res)
或者使用byte轉換爲二進制
shab1 = hashlib.sha1()
shab1.update(bytes(string,encoding='utf-8')) res = shab1.hexdigest() print("sha1採用byte轉換的結果:",res)
以上輸出:
sha1採用encode轉換加密結果: 458d32be8ea38b66300174970ab0a8c0b734252f
sha1採用byte轉換的結果: 458d32be8ea38b66300174970ab0a8c0b734252f
經常使用方法
- hash.update(arg) 更新哈希對象以字符串參數, 注意:若是同一個hash對象重複調用該方法,則m.update(a); m.update(b) 等效於 m.update(a+b),看下面例子
m = hashlib.md5()
m.update('a'.encode('utf-8')) res = m.hexdigest() print("第一次a加密:",res) m.update('b'.encode('utf-8')) res = m.hexdigest() print("第二次b加密:",res) m1 = hashlib.md5() m1.update('b'.encode('utf-8')) res = m1.hexdigest() print("b單獨加密:",res) m2 = hashlib.md5() m2.update('ab'.encode('utf-8')) res = m2.hexdigest() print("ab單獨加密:",res) 輸出結果: 第一次a加密: 0cc175b9c0f1b6a831c399e269772661 第二次b加密: 187ef4436122d1cc2f40dc2b92f0eba0 b單獨加密: 92eb5ffee6ae2fec3ad71c777531578f ab單獨加密: 187ef4436122d1cc2f40dc2b92f0eba0
-
hash.digest() 返回摘要,做爲二進制數據字符串值,
-
hash.hexdigest() 返回摘要,做爲十六進制數據字符串值,
-
hash.copy() 複製
高級加密
以上加密算法雖然依然很是厲害,但時候存在缺陷,即:經過撞庫能夠反解。因此,有必要對加密算法中添加自定義key再來作加密。
low = hashlib.md5()
low.update('ab'.encode('utf-8')) res = low.hexdigest() print("普通加密:",res) high = hashlib.md5(b'beyondjie') high.update('ab'.encode('utf-8')) res = high.hexdigest() print("採用key加密:",res) 輸出結果: 普通加密: 187ef4436122d1cc2f40dc2b92f0eba0 採用key加密: 1b073f6b8cffe609751e4c98537b7653
附加HMAC-SHA1各語言版本實現
在各大開放平臺大行其道的互聯網開發潮流中,調用各平臺的API接口過程當中,無一例外都會用到計算簽名值(sig值)。而在各類計算簽名的方法中,常常被採用的就是HMAC-SHA1,現對HMAC-SHA1作一個簡單的介紹:
HMAC,散列消息鑑別碼,基於密鑰的Hash算法認證協議。實現原理爲:利用已經公開的Hash函數和私有的密鑰,來生成固定長度的消息鑑別碼;
SHA一、MD5等Hash算法是比較經常使用的不可逆Hash簽名計算方法;
BASE64,將任意序列的8字節字符轉換爲人眼沒法直接識別的符號編碼的一種方法;
各個語言版本的實現爲:
Python版:
import hmac import hashlib import base64 hmac.new(Token,data,hashlib.sha1).digest().encode('base64').rstrip() Token:即接口的key data:要加密的數據 PHP版: base64_encode(hash_hmac("SHA1",clientStr,Token , true)) C++版(Openssl): HMAC( EVP_sha1(), /*key data*/ strKey.data(), /*key len*/ strKey.size(), /*data */(unsigned char*) strRandom.data(), /*data len*/ strRandom.size(), digest, &digest_len)) Shell版: echo -n '3f88a95c532bea70' | openssl dgst -hmac '123' -sha1 -binary | base64
1 logging模塊簡介
logging模塊是Python內置的標準模塊,主要用於輸出運行日誌,能夠設置輸出日誌的等級、日誌保存路徑、日誌文件回滾等;相比print,具有以下優勢:
- 能夠經過設置不一樣的日誌等級,在release版本中只輸出重要信息,而沒必要顯示大量的調試信息;
- print將全部信息都輸出到標準輸出中,嚴重影響開發者從標準輸出中查看其它數據;logging則能夠由開發者決定將信息輸出到什麼地方,以及怎麼輸出;
2 logging模塊使用
2.1 基本使用
配置logging基本的設置,而後在控制檯輸出日誌,
import logging logging.basicConfig(level = logging.INFO,format = '%(asctime)s - %(name)s - %(levelname)s - %(message)s') logger = logging.getLogger(__name__) logger.info("Start print log") logger.debug("Do something") logger.warning("Something maybe fail.") logger.info("Finish")
運行時,控制檯輸出,
2016-10-09 19:11:19,434 - __main__ - INFO - Start print log 2016-10-09 19:11:19,434 - __main__ - WARNING - Something maybe fail. 2016-10-09 19:11:19,434 - __main__ - INFO - Finish
logging中能夠選擇不少消息級別,如debug、info、warning、error以及critical。經過賦予logger或者handler不一樣的級別,開發者就能夠只輸出錯誤信息到特定的記錄文件,或者在調試時只記錄調試信息。
例如,咱們將logger的級別改成DEBUG,再觀察一下輸出結果,
logging.basicConfig(level = logging.DEBUG,format = '%(asctime)s - %(name)s - %(levelname)s - %(message)s')
控制檯輸出,能夠發現,輸出了debug的信息。
2016-10-09 19:12:08,289 - __main__ - INFO - Start print log 2016-10-09 19:12:08,289 - __main__ - DEBUG - Do something 2016-10-09 19:12:08,289 - __main__ - WARNING - Something maybe fail. 2016-10-09 19:12:08,289 - __main__ - INFO - Finish
logging.basicConfig函數各參數:
filename:指定日誌文件名;
filemode:和file函數意義相同,指定日誌文件的打開模式,'w'或者'a';
format:指定輸出的格式和內容,format能夠輸出不少有用的信息,
參數:做用
%(levelno)s:打印日誌級別的數值 %(levelname)s:打印日誌級別的名稱 %(pathname)s:打印當前執行程序的路徑,其實就是sys.argv[0] %(filename)s:打印當前執行程序名 %(funcName)s:打印日誌的當前函數 %(lineno)d:打印日誌的當前行號 %(asctime)s:打印日誌的時間 %(thread)d:打印線程ID %(threadName)s:打印線程名稱 %(process)d:打印進程ID %(message)s:打印日誌信息
datefmt:指定時間格式,同time.strftime();
level:設置日誌級別,默認爲logging.WARNNING;
stream:指定將日誌的輸出流,能夠指定輸出到sys.stderr,sys.stdout或者文件,默認輸出到sys.stderr,當stream和filename同時指定時,stream被忽略;
2.2 將日誌寫入到文件
2.2.1 將日誌寫入到文件
設置logging,建立一個FileHandler,並對輸出消息的格式進行設置,將其添加到logger,而後將日誌寫入到指定的文件中,
import logging logger = logging.getLogger(__name__) logger.setLevel(level = logging.INFO) handler = logging.FileHandler("log.txt") handler.setLevel(logging.INFO) formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') handler.setFormatter(formatter) logger.addHandler(handler) logger.info("Start print log") logger.debug("Do something") logger.warning("Something maybe fail.") logger.info("Finish")
log.txt中日誌數據爲,
2016-10-09 19:01:13,263 - __main__ - INFO - Start print log 2016-10-09 19:01:13,263 - __main__ - WARNING - Something maybe fail. 2016-10-09 19:01:13,263 - __main__ - INFO - Finish
2.2.2 將日誌同時輸出到屏幕和日誌文件
logger中添加StreamHandler,能夠將日誌輸出到屏幕上,
import logging logger = logging.getLogger(__name__) logger.setLevel(level = logging.INFO) handler = logging.FileHandler("log.txt") handler.setLevel(logging.INFO) formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') handler.setFormatter(formatter) console = logging.StreamHandler() console.setLevel(logging.INFO) logger.addHandler(handler) logger.addHandler(console) logger.info("Start print log") logger.debug("Do something") logger.warning("Something maybe fail.") logger.info("Finish")
能夠在log.txt文件和控制檯中看到,
2016-10-09 19:20:46,553 - __main__ - INFO - Start print log 2016-10-09 19:20:46,553 - __main__ - WARNING - Something maybe fail. 2016-10-09 19:20:46,553 - __main__ - INFO - Finish
能夠發現,logging有一個日誌處理的主對象,其餘處理方式都是經過addHandler添加進去,logging中包含的handler主要有以下幾種,
handler名稱:位置;做用 StreamHandler:logging.StreamHandler;日誌輸出到流,能夠是sys.stderr,sys.stdout或者文件 FileHandler:logging.FileHandler;日誌輸出到文件 BaseRotatingHandler:logging.handlers.BaseRotatingHandler;基本的日誌回滾方式 RotatingHandler:logging.handlers.RotatingHandler;日誌回滾方式,支持日誌文件最大數量和日誌文件回滾 TimeRotatingHandler:logging.handlers.TimeRotatingHandler;日誌回滾方式,在必定時間區域內回滾日誌文件 SocketHandler:logging.handlers.SocketHandler;遠程輸出日誌到TCP/IP sockets DatagramHandler:logging.handlers.DatagramHandler;遠程輸出日誌到UDP sockets SMTPHandler:logging.handlers.SMTPHandler;遠程輸出日誌到郵件地址 SysLogHandler:logging.handlers.SysLogHandler;日誌輸出到syslog NTEventLogHandler:logging.handlers.NTEventLogHandler;遠程輸出日誌到Windows NT/2000/XP的事件日誌 MemoryHandler:logging.handlers.MemoryHandler;日誌輸出到內存中的指定buffer HTTPHandler:logging.handlers.HTTPHandler;經過"GET"或者"POST"遠程輸出到HTTP服務器
2.2.3 日誌回滾
使用RotatingFileHandler,能夠實現日誌回滾,
import logging from logging.handlers import RotatingFileHandler logger = logging.getLogger(__name__) logger.setLevel(level = logging.INFO) #定義一個RotatingFileHandler,最多備份3個日誌文件,每一個日誌文件最大1K rHandler = RotatingFileHandler("log.txt",maxBytes = 1*1024,backupCount = 3) rHandler.setLevel(logging.INFO) formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') rHandler.setFormatter(formatter) console = logging.StreamHandler() console.setLevel(logging.INFO) console.setFormatter(formatter) logger.addHandler(rHandler) logger.addHandler(console) logger.info("Start print log") logger.debug("Do something") logger.warning("Something maybe fail.") logger.info("Finish")
能夠在工程目錄中看到,備份的日誌文件,
2016/10/09 19:36 732 log.txt 2016/10/09 19:36 967 log.txt.1 2016/10/09 19:36 985 log.txt.2 2016/10/09 19:36 976 log.txt.3
2.3 設置消息的等級
能夠設置不一樣的日誌等級,用於控制日誌的輸出,
日誌等級:使用範圍
FATAL:致命錯誤
CRITICAL:特別糟糕的事情,如內存耗盡、磁盤空間爲空,通常不多使用 ERROR:發生錯誤時,如IO操做失敗或者鏈接問題 WARNING:發生很重要的事件,可是並非錯誤時,如用戶登陸密碼錯誤 INFO:處理請求或者狀態變化等平常事務 DEBUG:調試過程當中使用DEBUG等級,如算法中每一個循環的中間狀態
2.4 捕獲traceback
Python中的traceback模塊被用於跟蹤異常返回信息,能夠在logging中記錄下traceback,
代碼,
import logging logger = logging.getLogger(__name__) logger.setLevel(level = logging.INFO) handler = logging.FileHandler("log.txt") handler.setLevel(logging.INFO) formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') handler.setFormatter(formatter) console = logging.StreamHandler() console.setLevel(logging.INFO) logger.addHandler(handler) logger.addHandler(console) logger.info("Start print log") logger.debug("Do something") logger.warning("Something maybe fail.") try: open("sklearn.txt","rb") except (SystemExit,KeyboardInterrupt): raise except Exception: logger.error("Faild to open sklearn.txt from logger.error",exc_info = True) logger.info("Finish")
控制檯和日誌文件log.txt中輸出,
Start print log Something maybe fail. Faild to open sklearn.txt from logger.error Traceback (most recent call last): File "G:\zhb7627\Code\Eclipse WorkSpace\PythonTest\test.py", line 23, in <module> open("sklearn.txt","rb") IOError: [Errno 2] No such file or directory: 'sklearn.txt' Finish
也可使用logger.exception(msg,_args),它等價於logger.error(msg,exc_info = True,_args),
將
logger.error("Faild to open sklearn.txt from logger.error",exc_info = True)
替換爲,
logger.exception("Failed to open sklearn.txt from logger.exception")
控制檯和日誌文件log.txt中輸出,
Start print log Something maybe fail. Failed to open sklearn.txt from logger.exception Traceback (most recent call last): File "G:\zhb7627\Code\Eclipse WorkSpace\PythonTest\test.py", line 23, in <module> open("sklearn.txt","rb") IOError: [Errno 2] No such file or directory: 'sklearn.txt' Finish
2.5 多模塊使用logging
主模塊mainModule.py,
import logging import subModule logger = logging.getLogger("mainModule") logger.setLevel(level = logging.INFO) handler = logging.FileHandler("log.txt") handler.setLevel(logging.INFO) formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') handler.setFormatter(formatter) console = logging.StreamHandler() console.setLevel(logging.INFO) console.setFormatter(formatter) logger.addHandler(handler) logger.addHandler(console) logger.info("creating an instance of subModule.subModuleClass") a = subModule.SubModuleClass() logger.info("calling subModule.subModuleClass.doSomething") a.doSomething() logger.info("done with subModule.subModuleClass.doSomething") logger.info("calling subModule.some_function") subModule.som_function() logger.info("done with subModule.some_function")
子模塊subModule.py,
import logging module_logger = logging.getLogger("mainModule.sub") class SubModuleClass(object): def __init__(self): self.logger = logging.getLogger("mainModule.sub.module") self.logger.info("creating an instance in SubModuleClass") def doSomething(self): self.logger.info("do something in SubModule") a = [] a.append(1) self.logger.debug("list a = " + str(a)) self.logger.info("finish something in SubModuleClass") def som_function(): module_logger.info("call function some_function")
執行以後,在控制和日誌文件log.txt中輸出,
2016-10-09 20:25:42,276 - mainModule - INFO - creating an instance of subModule.subModuleClass 2016-10-09 20:25:42,279 - mainModule.sub.module - INFO - creating an instance in SubModuleClass 2016-10-09 20:25:42,279 - mainModule - INFO - calling subModule.subModuleClass.doSomething 2016-10-09 20:25:42,279 - mainModule.sub.module - INFO - do something in SubModule 2016-10-09 20:25:42,279 - mainModule.sub.module - INFO - finish something in SubModuleClass 2016-10-09 20:25:42,279 - mainModule - INFO - done with subModule.subModuleClass.doSomething 2016-10-09 20:25:42,279 - mainModule - INFO - calling subModule.some_function 2016-10-09 20:25:42,279 - mainModule.sub - INFO - call function some_function 2016-10-09 20:25:42,279 - mainModule - INFO - done with subModule.some_function
首先在主模塊定義了logger'mainModule',並對它進行了配置,就能夠在解釋器進程裏面的其餘地方經過getLogger('mainModule')獲得的對象都是同樣的,不須要從新配置,能夠直接使用。定義的該logger的子logger,均可以共享父logger的定義和配置,所謂的父子logger是經過命名來識別,任意以'mainModule'開頭的logger都是它的子logger,例如'mainModule.sub'。
實際開發一個application,首先能夠經過logging配置文件編寫好這個application所對應的配置,能夠生成一個根logger,如'PythonAPP',而後在主函數中經過fileConfig加載logging配置,接着在application的其餘地方、不一樣的模塊中,可使用根logger的子logger,如'PythonAPP.Core','PythonAPP.Web'來進行log,而不須要反覆的定義和配置各個模塊的logger。
3 經過JSON或者YAML文件配置logging模塊
儘管能夠在Python代碼中配置logging,可是這樣並不夠靈活,最好的方法是使用一個配置文件來配置。在Python 2.7及之後的版本中,能夠從字典中加載logging配置,也就意味着能夠經過JSON或者YAML文件加載日誌的配置。
3.1 經過JSON文件配置
JSON配置文件,
{
"version":1, "disable_existing_loggers":false, "formatters":{ "simple":{ "format":"%(asctime)s - %(name)s - %(levelname)s - %(message)s" } }, "handlers":{ "console":{ "class":"logging.StreamHandler", "level":"DEBUG", "formatter":"simple", "stream":"ext://sys.stdout" }, "info_file_handler":{ "class":"logging.handlers.RotatingFileHandler", "level":"INFO", "formatter":"simple", "filename":"info.log", "maxBytes":"10485760", "backupCount":20, "encoding":"utf8" }, "error_file_handler":{ "class":"logging.handlers.RotatingFileHandler", "level":"ERROR", "formatter":"simple", "filename":"errors.log", "maxBytes":10485760, "backupCount":20, "encoding":"utf8" } }, "loggers":{ "my_module":{ "level":"ERROR", "handlers":["info_file_handler"], "propagate":"no" } }, "root":{ "level":"INFO", "handlers":["console","info_file_handler","error_file_handler"] } }
經過JSON加載配置文件,而後經過logging.dictConfig配置logging,
import json import logging.config import os def setup_logging(default_path = "logging.json",default_level = logging.INFO,env_key = "LOG_CFG"): path = default_path value = os.getenv(env_key,None) if value: path = value if os.path.exists(path): with open(path,"r") as f: config = json.load(f) logging.config.dictConfig(config) else: logging.basicConfig(level = default_level) def func(): logging.info("start func") logging.info("exec func") logging.info("end func") if __name__ == "__main__": setup_logging(default_path = "logging.json") func()
3.2 經過YAML文件配置
經過YAML文件進行配置,比JSON看起來更加簡介明瞭,
version: 1 disable_existing_loggers: False formatters: simple: format: "%(asctime)s - %(name)s - %(levelname)s - %(message)s" handlers: console: class: logging.StreamHandler level: DEBUG formatter: simple stream: ext://sys.stdout info_file_handler: class: logging.handlers.RotatingFileHandler level: INFO formatter: simple filename: info.log maxBytes: 10485760 backupCount: 20 encoding: utf8 error_file_handler: class: logging.handlers.RotatingFileHandler level: ERROR formatter: simple filename: errors.log maxBytes: 10485760 backupCount: 20 encoding: utf8 loggers: my_module: level: ERROR handlers: [info_file_handler] propagate: no root: level: INFO handlers: [console,info_file_handler,error_file_handler]
經過YAML加載配置文件,而後經過logging.dictConfig配置logging,
import yaml import logging.config import os def setup_logging(default_path = "logging.yaml",default_level = logging.INFO,env_key = "LOG_CFG"): path = default_path value = os.getenv(env_key,None) if value: path = value if os.path.exists(path): with open(path,"r") as f: config = yaml.load(f) logging.config.dictConfig(config) else: logging.basicConfig(level = default_level) def func(): logging.info("start func") logging.info("exec func") logging.info("end func") if __name__ == "__main__": setup_logging(default_path = "logging.yaml") func()
subprocess模塊
subprocess是Python 2.4中新增的一個模塊,它容許你生成新的進程,鏈接到它們的 input/output/error 管道,並獲取它們的返回(狀態)碼。這個模塊的目的在於替換幾個舊的模塊和方法,如:
- os.system
- os.spawn*
1. subprocess模塊中的經常使用函數
函數 | 描述 |
---|---|
subprocess.run() | Python 3.5中新增的函數。執行指定的命令,等待命令執行完成後返回一個包含執行結果的CompletedProcess類的實例。 |
subprocess.call() | 執行指定的命令,返回命令執行狀態,其功能相似於os.system(cmd)。 |
subprocess.check_call() | Python 2.5中新增的函數。 執行指定的命令,若是執行成功則返回狀態碼,不然拋出異常。其功能等價於subprocess.run(..., check=True)。 |
subprocess.check_output() | Python 2.7中新增的的函數。執行指定的命令,若是執行狀態碼爲0則返回命令執行結果,不然拋出異常。 |
subprocess.getoutput(cmd) | 接收字符串格式的命令,執行命令並返回執行結果,其功能相似於os.popen(cmd).read()和commands.getoutput(cmd)。 |
subprocess.getstatusoutput(cmd) | 執行cmd命令,返回一個元組(命令執行狀態, 命令執行結果輸出),其功能相似於commands.getstatusoutput()。 |
說明:
- 在Python 3.5以後的版本中,官方文檔中提倡經過subprocess.run()函數替代其餘函數來使用subproccess模塊的功能;
- 在Python 3.5以前的版本中,咱們能夠經過subprocess.call(),subprocess.getoutput()等上面列出的其餘函數來使用subprocess模塊的功能;
- subprocess.run()、subprocess.call()、subprocess.check_call()和subprocess.check_output()都是經過對subprocess.Popen的封裝來實現的高級函數,所以若是咱們須要更復雜功能時,能夠經過subprocess.Popen來完成。
- subprocess.getoutput()和subprocess.getstatusoutput()函數是來自Python 2.x的commands模塊的兩個遺留函數。它們隱式的調用系統shell,而且不保證其餘函數所具備的安全性和異常處理的一致性。另外,它們從Python 3.3.4開始才支持Windows平臺。
2. 上面各函數的定義及參數說明
函數參數列表:
subprocess.run(args, *, stdin=None, input=None, stdout=None, stderr=None, shell=False, timeout=None, check=False, universal_newlines=False) subprocess.call(args, *, stdin=None, stdout=None, stderr=None, shell=False, timeout=None) subprocess.check_call(args, *, stdin=None, stdout=None, stderr=None, shell=False, timeout=None) subprocess.check_output(args, *, stdin=None, stderr=None, shell=False, universal_newlines=False, timeout=None) subprocess.getstatusoutput(cmd) subprocess.getoutput(cmd)
參數說明:
- args: 要執行的shell命令,默認應該是一個字符串序列,如['df', '-Th']或('df', '-Th'),也能夠是一個字符串,如'df -Th',可是此時須要把shell參數的值置爲True。
- shell: 若是shell爲True,那麼指定的命令將經過shell執行。若是咱們須要訪問某些shell的特性,如管道、文件名通配符、環境變量擴展功能,這將是很是有用的。固然,python自己也提供了許多相似shell的特性的實現,如glob、fnmatch、os.walk()、os.path.expandvars()、os.expanduser()和shutil等。
- check: 若是check參數的值是True,且執行命令的進程以非0狀態碼退出,則會拋出一個CalledProcessError的異常,且該異常對象會包含 參數、退出狀態碼、以及stdout和stderr(若是它們有被捕獲的話)。
- stdout, stderr:
- run()函數默認不會捕獲命令執行結果的正常輸出和錯誤輸出,若是咱們向獲取這些內容須要傳遞subprocess.PIPE,而後能夠經過返回的CompletedProcess類實例的stdout和stderr屬性或捕獲相應的內容;
- call()和check_call()函數返回的是命令執行的狀態碼,而不是CompletedProcess類實例,因此對於它們而言,stdout和stderr不適合賦值爲subprocess.PIPE;
- check_output()函數默認就會返回命令執行結果,因此不用設置stdout的值,若是咱們但願在結果中捕獲錯誤信息,能夠執行stderr=subprocess.STDOUT。
- input: 該參數是傳遞給Popen.communicate(),一般該參數的值必須是一個字節序列,若是universal_newlines=True,則其值應該是一個字符串。
- universal_newlines: 該參數影響的是輸入與輸出的數據格式,好比它的值默認爲False,此時stdout和stderr的輸出是字節序列;當該參數的值設置爲True時,stdout和stderr的輸出是字符串。
3. subprocess.CompletedProcess類介紹
須要說明的是,subprocess.run()函數是Python3.5中新增的一個高級函數,其返回值是一個subprocess.CompletedPorcess類的實例,所以,subprocess.completedPorcess類也是Python 3.5中才存在的。它表示的是一個已結束進程的狀態信息,它所包含的屬性以下:
- args: 用於加載該進程的參數,這多是一個列表或一個字符串
- returncode: 子進程的退出狀態碼。一般狀況下,退出狀態碼爲0則表示進程成功運行了;一個負值-N表示這個子進程被信號N終止了
- stdout: 從子進程捕獲的stdout。這一般是一個字節序列,若是run()函數被調用時指定universal_newlines=True,則該屬性值是一個字符串。若是run()函數被調用時指定stderr=subprocess.STDOUT,那麼stdout和stderr將會被整合到這一個屬性中,且stderr將會爲None
- stderr: 從子進程捕獲的stderr。它的值與stdout同樣,是一個字節序列或一個字符串。若是stderr滅有被捕獲的話,它的值就爲None
- check_returncode(): 若是returncode是一個非0值,則該方法會拋出一個CalledProcessError異常。
4. 實例
subprocess.run()
>>> subprocess.run(["ls", "-l"]) # doesn't capture output CompletedProcess(args=['ls', '-l'], returncode=0) >>> subprocess.run("exit 1", shell=True, check=True) Traceback (most recent call last): ... subprocess.CalledProcessError: Command 'exit 1' returned non-zero exit status 1 >>> subprocess.run(["ls", "-l", "/dev/null"], stdout=subprocess.PIPE) CompletedProcess(args=['ls', '-l', '/dev/null'], returncode=0, stdout=b'crw-rw-rw- 1 root root 1, 3 Jan 23 16:23 /dev/null\n')
subprocess.call()
>>> subprocess.call(['ls', '-l']) 總用量 160 drwxr-xr-x 2 wader wader 4096 12月 7 2015 公共的 drwxr-xr-x 2 wader wader 4096 12月 7 2015 模板 drwxr-xr-x 2 wader wader 4096 12月 7 2015 視頻 drwxr-xr-x 2 wader wader 4096 12月 7 2015 圖片 drwxr-xr-x 2 wader wader 4096 12月 7 2015 文檔 drwxr-xr-x 2 wader wader 4096 4月 13 2016 下載 drwxr-xr-x 2 wader wader 4096 12月 7 2015 音樂 drwxr-xr-x 7 wader wader 4096 5月 26 2016 桌面 0 >>> subprocess.call('ls -l', shell=True) 總用量 160 drwxr-xr-x 2 wader wader 4096 12月 7 2015 公共的 drwxr-xr-x 2 wader wader 4096 12月 7 2015 模板 drwxr-xr-x 2 wader wader 4096 12月 7 2015 視頻 drwxr-xr-x 2 wader wader 4096 12月 7 2015 圖片 drwxr-xr-x 2 wader wader 4096 12月 7 2015 文檔 drwxr-xr-x 2 wader wader 4096 4月 13 2016 下載 drwxr-xr-x 2 wader wader 4096 12月 7 2015 音樂 drwxr-xr-x 7 wader wader 4096 5月 26 2016 桌面 0 >>> subprocess.call(['ls', '-l'], stdout=subprocess.DEVNULL) 0 >>> subprocess.call(['ls', '-l', '/test']) ls: 沒法訪問/test: 沒有那個文件或目錄 2
suprocess.check_call()
>>> subprocess.check_call(['ls', '-l']) 總用量 160 drwxr-xr-x 2 wader wader 4096 12月 7 2015 公共的 drwxr-xr-x 2 wader wader 4096 12月 7 2015 模板 drwxr-xr-x 2 wader wader 4096 12月 7 2015 視頻 drwxr-xr-x 2 wader wader 4096 12月 7 2015 圖片 drwxr-xr-x 2 wader wader 4096 12月 7 2015 文檔 drwxr-xr-x 2 wader wader 4096 4月 13 2016 下載 drwxr-xr-x 2 wader wader 4096 12月 7 2015 音樂 drwxr-xr-x 7 wader wader 4096 5月 26 2016 桌面 0 >>> subprocess.check_call('ls -l', shell=True) 總用量 160 drwxr-xr-x 2 wader wader 4096 12月 7 2015 公共的 drwxr-xr-x 2 wader wader 4096 12月 7 2015 模板 drwxr-xr-x 2 wader wader 4096 12月 7 2015 視頻 drwxr-xr-x 2 wader wader 4096 12月 7 2015 圖片 drwxr-xr-x 2 wader wader 4096 12月 7 2015 文檔 drwxr-xr-x 2 wader wader 4096 4月 13 2016 下載 drwxr-xr-x 2 wader wader 4096 12月 7 2015 音樂 drwxr-xr-x 7 wader wader 4096 5月 26 2016 桌面 0 >>> subprocess.check_call('ls -l /test', shell=True) ls: 沒法訪問/test: 沒有那個文件或目錄 Traceback (most recent call last): File "<stdin>", line 1, in <module> File "/usr/lib/python3.4/subprocess.py", line 557, in check_call raise CalledProcessError(retcode, cmd) subprocess.CalledProcessError: Command 'ls -l /test' returned non-zero exit status 2
sbuprocess.check_output()
>>> ret = subprocess.check_output(['ls', '-l']) >>> print(ret) b' \xe5\x85\xac\xe5\x85\xb1\xe7\x9a\x84\ndrwxr-xr-x 2 wader wader 4096 12\xe6\x9c\x88 7 2015 \xe6\xa8\xa1\xe6\x9d\xbf\ndrwxr-xr-x 2 wader wader 4096 12\xe6\x9c\x88 7 2015 \xe8\xa7\x86\xe9\xa2\x91\ndrwxr-xr-x 2 wader wader 4096 12\xe6\x9c\x88 7 2015 \xe5\x9b\xbe\xe7\x89\x87\ndrwxr-xr-x 2 wader wader 4096 12\xe6\x9c\x88 7 2015 \xe6\x96\x87\xe6\xa1\xa3\ndrwxr-xr-x 2 wader wader 4096 4\xe6\x9c\x88 13 2016 \xe4\xb8\x8b\xe8\xbd\xbd\ndrwxr-xr-x 2 wader wader 4096 12\xe6\x9c\x88 7 2015 \xe9\x9f\xb3\xe4\xb9\x90\ndrwxr-xr-x 7 wader wader 4096 5\xe6\x9c\x88 26 2016 \xe6\xa1\x8c\xe9\x9d\xa2\n' >>> ret = subprocess.check_output(['ls', '-l'], universal_newlines=True) >>> print(ret) 總用量 160 drwxr-xr-x 2 wader wader 4096 12月 7 2015 公共的 drwxr-xr-x 2 wader wader 4096 12月 7 2015 模板 drwxr-xr-x 2 wader wader 4096 12月 7 2015 視頻 drwxr-xr-x 2 wader wader 4096 12月 7 2015 圖片 drwxr-xr-x 2 wader wader 4096 12月 7 2015 文檔 drwxr-xr-x 2 wader wader 4096 4月 13 2016 下載 drwxr-xr-x 2 wader wader 4096 12月 7 2015 音樂 drwxr-xr-x 7 wader wader 4096 5月 26 2016 桌面
subprocess.getoutput()與subprocess.getstatusoutput()
>>> ret = subprocess.getoutput('ls -l') >>> print(ret) 總用量 160 drwxr-xr-x 2 wader wader 4096 12月 7 2015 公共的 drwxr-xr-x 2 wader wader 4096 12月 7 2015 模板 drwxr-xr-x 2 wader wader 4096 12月 7 2015 視頻 drwxr-xr-x 2 wader wader 4096 12月 7 2015 圖片 drwxr-xr-x 2 wader wader 4096 12月 7 2015 文檔 drwxr-xr-x 2 wader wader 4096 4月 13 2016 下載 drwxr-xr-x 2 wader wader 4096 12月 7 2015 音樂 drwxr-xr-x 7 wader wader 4096 5月 26 2016 桌面 >>> retcode, output = subprocess.getstatusoutput('ls -l') >>> print(retcode) 0 >>> print(output) 總用量 160 drwxr-xr-x 2 wader wader 4096 12月 7 2015 公共的 drwxr-xr-x 2 wader wader 4096 12月 7 2015 模板 drwxr-xr-x 2 wader wader 4096 12月 7 2015 視頻 drwxr-xr-x 2 wader wader 4096 12月 7 2015 圖片 drwxr-xr-x 2 wader wader 4096 12月 7 2015 文檔 drwxr-xr-x 2 wader wader 4096 4月 13 2016 下載 drwxr-xr-x 2 wader wader 4096 12月 7 2015 音樂 drwxr-xr-x 7 wader wader 4096 5月 26 2016 桌面 >>> retcode, output = subprocess.getstatusoutput('ls -l /test') >>> print(retcode) 2 >>> print(output) ls: 沒法訪問/test: 沒有那個文件或目錄
3、subprocess.Popen介紹
該類用於在一個新的進程中執行一個子程序。前面咱們提到過,上面介紹的這些函數都是基於subprocess.Popen類實現的,經過使用這些被封裝後的高級函數能夠很方面的完成一些常見的需求。因爲subprocess模塊底層的進程建立和管理是由Popen類來處理的,所以,當咱們沒法經過上面哪些高級函數來實現一些不太常見的功能時就能夠經過subprocess.Popen類提供的靈活的api來完成。
1.subprocess.Popen的構造函數
class subprocess.Popen(args, bufsize=-1, executable=None, stdin=None, stdout=None, stderr=None, preexec_fn=None, close_fds=True, shell=False, cwd=None, env=None, universal_newlines=False, startup_info=None, creationflags=0, restore_signals=True, start_new_session=False, pass_fds=())
參數說明:
- args: 要執行的shell命令,能夠是字符串,也能夠是命令各個參數組成的序列。當該參數的值是一個字符串時,該命令的解釋過程是與平臺相關的,所以一般建議將args參數做爲一個序列傳遞。
- bufsize: 指定緩存策略,0表示不緩衝,1表示行緩衝,其餘大於1的數字表示緩衝區大小,負數 表示使用系統默認緩衝策略。
- stdin, stdout, stderr: 分別表示程序標準輸入、輸出、錯誤句柄。
- preexec_fn: 用於指定一個將在子進程運行以前被調用的可執行對象,只在Unix平臺下有效。
- close_fds: 若是該參數的值爲True,則除了0,1和2以外的全部文件描述符都將會在子進程執行以前被關閉。
- shell: 該參數用於標識是否使用shell做爲要執行的程序,若是shell值爲True,則建議將args參數做爲一個字符串傳遞而不要做爲一個序列傳遞。
- cwd: 若是該參數值不是None,則該函數將會在執行這個子進程以前改變當前工做目錄。
- env: 用於指定子進程的環境變量,若是env=None,那麼子進程的環境變量將從父進程中繼承。若是env!=None,它的值必須是一個映射對象。
- universal_newlines: 若是該參數值爲True,則該文件對象的stdin,stdout和stderr將會做爲文本流被打開,不然他們將會被做爲二進制流被打開。
- startupinfo和creationflags: 這兩個參數只在Windows下有效,它們將被傳遞給底層的CreateProcess()函數,用於設置子進程的一些屬性,如主窗口的外觀,進程優先級等。
2. subprocess.Popen類的實例可調用的方法
方法 | 描述 |
---|---|
Popen.poll() | 用於檢查子進程(命令)是否已經執行結束,沒結束返回None,結束後返回狀態碼。 |
Popen.wait(timeout=None) | 等待子進程結束,並返回狀態碼;若是在timeout指定的秒數以後進程尚未結束,將會拋出一個TimeoutExpired異常。 |
Popen.communicate(input=None, timeout=None) | 該方法可用來與進程進行交互,好比發送數據到stdin,從stdout和stderr讀取數據,直到到達文件末尾。 |
Popen.send_signal(signal) | 發送指定的信號給這個子進程。 |
Popen.terminate() | 中止該子進程。 |
Popen.kill() | 殺死該子進程。 |
關於communicate()方法的說明:
- 該方法中的可選參數 input 應該是將被髮送給子進程的數據,或者如沒有數據發送給子進程,該參數應該是None。input參數的數據類型必須是字節串,若是universal_newlines參數值爲True,則input參數的數據類型必須是字符串。
- 該方法返回一個元組(stdout_data, stderr_data),這些數據將會是字節穿或字符串(若是universal_newlines的值爲True)。
- 若是在timeout指定的秒數後該進程尚未結束,將會拋出一個TimeoutExpired異常。捕獲這個異常,而後從新嘗試通訊不會丟失任何輸出的數據。可是超時以後子進程並無被殺死,爲了合理的清除相應的內容,一個好的應用應該手動殺死這個子進程來結束通訊。
- 須要注意的是,這裏讀取的數據是緩衝在內存中的,因此,若是數據大小很是大或者是無限的,就不該該使用這個方法。
3. subprocess.Popen使用實例
實例1:
>>> import subprocess
>>>
>>> p = subprocess.Popen('df -Th', stdout=subprocess.PIPE, shell=True) >>> print(p.stdout.read()) Filesystem Type Size Used Avail Use% Mounted on /dev/vda1 ext4 40G 12G 26G 31% / devtmpfs devtmpfs 3.9G 0 3.9G 0% /dev tmpfs tmpfs 3.9G 0 3.9G 0% /dev/shm tmpfs tmpfs 3.9G 386M 3.5G 10% /run tmpfs tmpfs 3.9G 0 3.9G 0% /sys/fs/cgroup tmpfs tmpfs 783M 0 783M 0% /run/user/0 tmpfs tmpfs 783M 0 783M 0% /run/user/1000
實例2:
>>> obj = subprocess.Popen(["python"], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE) >>> obj.stdin.write('print(1) \n') >>> obj.stdin.write('print(2) \n') >>> obj.stdin.write('print(3) \n') >>> out,err = obj.communicate() >>> print(out) 1 2 3 >>> print(err)
實例3:
>>> obj = subprocess.Popen(["python"], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE) >>> out,err = obj.communicate(input='print(1) \n') >>> print(out) 1 >>> print(err)
實例4:
實現相似df -Th | grep data
命令的功能,實際上就是實現shell中管道的共功能。
>>> >>> p1 = subprocess.Popen(['df', '-Th'], stdout=subprocess.PIPE) >>> p2 = subprocess.Popen(['grep', 'data'], stdin=p1.stdout, stdout=subprocess.PIPE) >>> out,err = p2.communicate() >>> print(out) /dev/vdb1 ext4 493G 4.8G 463G 2% /data /dev/vdd1 ext4 1008G 420G 537G 44% /data1 /dev/vde1 ext4 985G 503G 432G 54% /data2 >>> print(err) None
4、總結
那麼咱們到底該用哪一個模塊、哪一個函數來執行命令與系統及系統進行交互呢?下面咱們來作個總結:
- 首先應該知道的是,Python2.4版本引入了subprocess模塊用來替換os.system()、os.popen()、os.spawn*()等函數以及commands模塊;也就是說若是你使用的是Python 2.4及以上的版本就應該使用subprocess模塊了。
- 若是你的應用使用的Python 2.4以上,可是是Python 3.5如下的版本,Python官方給出的建議是使用subprocess.call()函數。Python 2.5中新增了一個subprocess.check_call()函數,Python 2.7中新增了一個subprocess.check_output()函數,這兩個函數也能夠按照需求進行使用。
- 若是你的應用使用的是Python 3.5及以上的版本(目前應該還不多),Python官方給出的建議是儘可能使用subprocess.run()函數。
- 當subprocess.call()、subprocess.check_call()、subprocess.check_output()和subprocess.run()這些高級函數沒法知足需求時,咱們可使用subprocess.Popen類來實現咱們須要的複雜功能。
json ,pickle模塊
JSON(JavaScript Object Notation, JS 對象標記) 是一種輕量級的數據交換格式。JSON的數據格式其實就是python裏面的字典格式,裏面能夠包含方括號括起來的數組,也就是python裏面的列表。
在python中,有專門處理json格式的模塊—— json 和 picle模塊
Json 模塊提供了四個方法: dumps、dump、loads、load
def dumps(obj, skipkeys=False, ensure_ascii=True, check_circular=True, allow_nan=True, cls=None, indent=None, separators=None, default=None, sort_keys=False, **kw): # Serialize ``obj`` to a JSON formatted ``str``. # 序列號 「obj」 數據類型 轉換爲 JSON格式的字符串
def dump(obj, fp, skipkeys=False, ensure_ascii=True, check_circular=True, allow_nan=True, cls=None, indent=None, separators=None, default=None, sort_keys=False, **kw): """Serialize ``obj`` as a JSON formatted stream to ``fp`` (a ``.write()``-supporting file-like object). 我理解爲兩個動做,一個動做是將」obj「轉換爲JSON格式的字符串,還有一個動做是將字符串寫入到文件中,也就是說文件描述符fp是必需要的參數 """
示例代碼:
>>> import json >>> json.dumps([]) # dumps能夠格式化全部的基本數據類型爲字符串 '[]' >>> json.dumps(1) # 數字 '1' >>> json.dumps('1') # 字符串 '"1"' >>> dict = {"name":"Tom", "age":23} >>> json.dumps(dict) # 字典 '{"name": "Tom", "age": 23}'
a = {"name":"Tom", "age":23} with open("test.json", "w", encoding='utf-8') as f: # indent 超級好用,格式化保存字典,默認爲None,小於0爲零個空格 f.write(json.dumps(a, indent=4)) # json.dump(a,f,indent=4) # 和上面的效果同樣
保存的文件效果:
二. loads 和 load
loads和load 反序列化方法
查看源碼:
def loads(s, encoding=None, cls=None, object_hook=None, parse_float=None, parse_int=None, parse_constant=None, object_pairs_hook=None, **kw): """Deserialize ``s`` (a ``str`` instance containing a JSON document) to a Python object. 將包含str類型的JSON文檔反序列化爲一個python對象"""
def load(fp, cls=None, object_hook=None, parse_float=None, parse_int=None, parse_constant=None, object_pairs_hook=None, **kw): """Deserialize ``fp`` (a ``.read()``-supporting file-like object containing a JSON document) to a Python object. 將一個包含JSON格式數據的可讀文件飯序列化爲一個python對象"""
實例:
>>> json.loads('{"name":"Tom", "age":23}') {'age': 23, 'name': 'Tom'}
import json with open("test.json", "r", encoding='utf-8') as f: aa = json.loads(f.read()) f.seek(0) bb = json.load(f) # 與 json.loads(f.read()) print(aa) print(bb) # 輸出: {'name': 'Tom', 'age': 23} {'name': 'Tom', 'age': 23}
三. json 和 pickle 模塊
json模塊和pickle模塊都有 dumps、dump、loads、load四種方法,並且用法同樣。
不用的是json模塊序列化出來的是通用格式,其它編程語言都認識,就是普通的字符串,
而picle模塊序列化出來的只有python能夠認識,其餘編程語言不認識的,表現爲亂碼
不過picle能夠序列化函數,可是其餘文件想用該函數,在該文件中須要有該文件的定義(定義和參數必須相同,內容能夠不一樣)
四. python對象(obj) 與json對象的對應關係
+-------------------+---------------+ | Python | JSON | +===================+===============+ | dict | object | +-------------------+---------------+ | list, tuple | array | +-------------------+---------------+ | str | string | +-------------------+---------------+ | int, float | number | +-------------------+---------------+ | True | true | +-------------------+---------------+ | False | false | +-------------------+---------------+ | None | null | +-------------------+---------------+
五. 總結
1. json序列化方法:
dumps:無文件操做 dump:序列化+寫入文件
2. json反序列化方法:
loads:無文件操做 load: 讀文件+反序列化
3. json模塊序列化的數據 更通用
picle模塊序列化的數據 僅python可用,但功能強大,能夠序列號函數
4. json模塊能夠序列化和反序列化的 數據類型 見 python對象(obj) 與json對象的對應關係表
5. 格式化寫入文件利用 indent = 4
ElementTree是python的XML處理模塊
構建
#encoding=utf-8 import xml.etree.ElementTree as ET #新建xml文件 def buildNewsXmlFile(): #設置一個新節點,並設置其標籤爲root root = ET.Element("root") #在root下新建兩個子節點,設置其名稱分別爲sina和chinabyte sina = ET.SubElement(root, "sina") chinabyte = ET.SubElement(root, "chinabyte") #在sina下新建兩個子節點,設置其節點名稱分別爲number和first sina_number = ET.SubElement(sina, "number") sina_number.text = "1" sina_first = ET.SubElement(sina, "first") sina_first.text = "http://roll.tech.sina.com.cn/internet_all/index_1.shtml" #在chinabyte下新建兩個子節點,設置其節點名稱爲number和first chinabyte_number = ET.SubElement(chinabyte, "number") chinabyte_number.text = "1" chinabyte_first = ET.SubElement(chinabyte, "first") chinabyte_first.text = "http://www.chinabyte.com/more/124566.shtml" #將節點數信息保存在ElementTree中,而且保存爲XML格式文件 tree = ET.ElementTree(root) tree.write("urlfile.xml")
解析和修改XML文件
<?xml version="1.0"?> <data> <country name="Liechtenstein"> <rank>1</rank> <year>2008</year> <gdppc>141100</gdppc> <neighbor name="Austria" direction="E"/> <neighbor name="Switzerland" direction="W"/> </country> <country name="Singapore"> <rank>4</rank> <year>2011</year> <gdppc>59900</gdppc> <neighbor name="Malaysia" direction="N"/> </country> <country name="Panama"> <rank>68</rank> <year>2011</year> <gdppc>13600</gdppc> <neighbor name="Costa Rica" direction="W"/> <neighbor name="Colombia" direction="E"/> </country> </data>
#解析Xml文件 def parseXmlFile(xml_name): #將XMl文件加載並返回一個ELementTree對象 tree = ET.parse(xml_name) #獲得第一個匹配sina標籤的Element對象 sina = tree.find("contry") #獲得sina的SubElement for sub_tag in sina: print sub_tag.text #獲得全部匹配sina標籤的Element對象的list集合 list_contry = tree.findall("contry") for contry in list_contry: for sub_tag in contry: print sub_tag.text #修改xml文件 for rank in tree.iter('rank') new_rank = int(rank.text)+1 rank.text = str(new_rank) rank.set('updated', 'yes') tree.write(xml_name)第一次的輸出是:1,2008,14100
<?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>
configparser 簡介
configparser 是 Pyhton 標準庫中用來解析配置文件的模塊,而且內置方法和字典很是接近。Python2.x 中名爲 ConfigParser,3.x 已改名小寫,並加入了一些新功能。
配置文件的格式以下:
[DEFAULT]
ServerAliveInterval = 45 Compression = yes CompressionLevel = 9 ForwardX11 = yes [bitbucket.org] User = Tom [topsecret.com] Port: 50022 ForwardX11: no
「[ ]」包含的爲 section,section 下面爲相似於 key - value 的配置內容;
configparser 默認支持 ‘=’ ‘:’ 兩種分隔。
configparser 經常使用方法
初始化實例
使用 configparser 首先須要初始化實例,並讀取配置文件:
>>> import configparser >>> config = configparser.ConfigParser() # 注意大小寫 >>> config.read("config.ini") # 配置文件的路徑 ["config.ini"]
或者能夠直接讀字典
>>> parser = configparser.ConfigParser()
>>> parser.read_dict({'section1': {'key1': 'value1', ... 'key2': 'value2', ... 'key3': 'value3'}, ... 'section2': {'keyA': 'valueA', ... 'keyB': 'valueB', ... 'keyC': 'valueC'}, ... 'section3': {'foo': 'x', ... 'bar': 'y', ... 'baz': 'z'} ... })
獲取全部 sections
>>> config.sections() ['bitbucket.org', 'topsecret.com'] # 注意會過濾掉[DEFAULT]
獲取指定 section 的 keys & values
>>> config.items('topsecret.com') >>>> [('port', '50022'), ('forwardx11', 'no')] # 注意items()返回的字符串會全變成小寫
獲取指定 section 的 keys
>>> config.options('topsecret.com') ['Port', 'ForwardX11']
>>> for option in config['topsecret.com']: ... print(option) Port ForwardX11
獲取指定 key 的 value
>>> config['bitbucket.org']['User'] 'Tom'
>>> config.get('bitbucket.org', 'User') 'Tom' >>> config.getint('topsecret.com', 'Port') 50022
檢查
>>> 'DEFAULT' in config True >>> 'test' in config['section_test'] False >>> 'Tom' in config['bitbucket.org']['User'] True
>>> config.has_section('bitbucket.org') True >>> config.has_option('section_test', 'test') False
添加
>>> config.add_section('Section_1') >>> config.set('Section_1', 'key_1', 'value_1') # 注意鍵值是用set()方法 >>> config.write(open('config.ini', 'w')) # 必定要寫入才生效
刪除
>>> config.remove_option('Section_1', 'key_1') True >>> config.remove_section('Section_1') True >>> config.clear() # 清空除[DEFAULT]以外全部內容 >>> config.write(open('config.ini', 'w'))
關於 [DEFAULT]
[DEFAULT] 通常包含 ini 格式配置文件的默認項,因此 configparser 部分方法會自動跳過這個 section 。
前面已經提到 sections() 是獲取不到的,還有刪除方法對 [DEFAULT] 也無效:
>>> config.remove_section('DEFAULT') False >>> config.clear() >>> 'DEFAULT' in config True >>> 'ForwardX11' in config['DEFAULT'] True >>> config.sections() []
但指定刪除和修改 [DEFAULT] 裏的 keys & values 是能夠的:
>>> config.remove_option('DEFAULT', 'ForwardX11') True >>> config.set('DEFAULT', 'ForwardX11','no') >>> config['DEFAULT']['ForwardX11'] 'no'
還有個特殊的是,has_section() 也無效,能夠和 in 區別使用
>>> config.has_section('DEFAULT') False >>> 'DEFAULT' in config True
更多用法請看官方文檔:https://docs.python.org/3.6/library/configparser.html
randmon(獲取隨機數)
random.random
random.random()用於生成一個0到1的隨機符點數: 0 <= n < 1.0
random.uniform
random.uniform(a, b),用於生成一個指定範圍內的隨機符點數,兩個參數其中一個是上限,一個是下限。若是a > b,則生成的隨機數n: a <= n <= b。若是 a <b, 則 b <= n <= a
print random.uniform(10, 20)
print random.uniform(20, 10)
# 18.7356606526
# 12.5798298022
random.randint
random.randint(a, b),用於生成一個指定範圍內的整數。其中參數a是下限,參數b是上限,生成的隨機數n: a <= n <= b
print random.randint(12, 20) # 生成的隨機數 n: 12 <= n <= 20
print random.randint(20, 20) # 結果永遠是20
# print random.randint(20, 10) # 該語句是錯誤的。下限必須小於上限
random.randrange
random.randrange([start], stop[, step]),從指定範圍內,按指定基數遞增的集合中 獲取一個隨機數。如:random.randrange(10, 100, 2),結果至關於從[10, 12, 14, 16, ... 96, 98]序列中獲取一個隨機數。random.randrange(10, 100, 2)在結果上與 random.choice(range(10, 100, 2) 等效
random.choice
random.choice從序列中獲取一個隨機元素。其函數原型爲:random.choice(sequence)。參數sequence表示一個有序類型。這裏要說明 一下:sequence在python不是一種特定的類型,而是泛指一系列的類型。list, tuple, 字符串都屬於sequence。有關sequence能夠查看python手冊數據模型這一章。下面是使用choice的一些例子:
print random.choice("學習Python")
print random.choice(["JGood", "is", "a", "handsome", "boy"])
print random.choice(("Tuple", "List", "Dict"))
random.shuffle
random.shuffle(x[, random]),用於將一個列表中的元素打亂。如:
p = ["Python", "is", "powerful", "simple", "and so on..."]
random.shuffle(p)
print p
# ['powerful', 'simple', 'is', 'Python', 'and so on...']
random.sample
random.sample(sequence, k),從指定序列中隨機獲取指定長度的片段。sample函數不會修改原有序列
list = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
slice = random.sample(list, 5) # 從list中隨機獲取5個元素,做爲一個片段返回
print slice
print list # 原有序列並無改變
隨機整數:
>>> random.randint(0,99)
# 21
隨機選取0到100間的偶數:
>>> random.randrange(0, 101, 2)
# 42
隨機浮點數:
>>> random.random()
0.85415370477785668
>>> random.uniform(1, 10)
# 5.4221167969800881
隨機字符:
>>> random.choice('abcdefg&#%^*f')
# 'd'
多個字符中選取特定數量的字符:
random.sample('abcdefghij', 3)
# ['a', 'd', 'b']
多個字符中選取特定數量的字符組成新字符串:
>>> import string
>>> string.join( random.sample(['a','b','c','d','e','f','g','h','i','j'], 3) ).replace(" ","")
# 'fih'
隨機選取字符串:
>>> random.choice ( ['apple', 'pear', 'peach', 'orange', 'lemon'] )
# 'lemon'
洗牌:
>>> items = [1, 2, 3, 4, 5, 6]
>>> random.shuffle(items)
>>> items
# [3, 2, 5, 6, 4, 1]
shutil模塊
引入: import shutil
copy()
功能:複製文件 格式:shutil.copy('來源文件','目標地址') 返回值:複製以後的路徑
copy2()
功能:複製文件,保留元數據 格式:shutil.copy2('來源文件','目標地址') 返回值:複製以後的路徑
copyfileobj()
將一個文件的內容拷貝的另一個文件當中 格式:shutil.copyfileobj(open(來源文件,'r'),open('目標文件','w')) 返回值:無
copyfile()
功能:將一個文件的內容拷貝的另一個文件當中 格式:shutil.copyfile(來源文件,目標文件) 返回值:目標文件的路徑
copytree()
功能:複製整個文件目錄 格式:shutil.copytree(來源目錄,目標目錄) 返回值:目標目錄的路徑 注意:不管文件夾是否爲空,都可以複製,並且會複製文件夾中的全部內容
copymode()
功能:拷貝權限
copystat()
功能:拷貝元數據(狀態)
rmtree()
功能:移除整個目錄,不管是否空 格式:shutil.rmtree(目錄路徑) 返回值:無
move()
功能:移動文件或者文件夾 格式:shutil.move(來源地址,目標地址) 返回值:目標地址
which()
功能:檢測命令對應的文件路徑 格式:shutil.which(‘命令字符串’) 返回值:命令文件所在位置 注意:window和linux不太同樣。 window的命令都是.exe結尾,linux則不是
disk_usage()
功能:檢測磁盤使用信息 格式:disk_usage(‘盤符’) 返回值:元組
歸檔和解包操做
歸檔:將多個文件合併到一個文件當中,這種操做方式就是歸檔。
解包:將歸檔的文件進行釋放。
壓縮:壓縮時將多個文件進行有損或者無損的合併到一個文件當中。
解壓縮:就是壓縮的反向操做,將壓縮文件中的多個文件,釋放出來。
注意:壓縮屬於歸檔!
make_archive()
功能:歸檔函數,歸檔操做 格式:shutil.make_archive('目標文件路徑','歸檔文件後綴','須要歸檔的目錄') 返回值:歸檔文件的最終路徑
unpack_archive()
功能:解包操做 格式:shutil.unpack_archive('歸檔文件路徑','解包目標文件夾') 返回值:None 注意:文件夾不存在會新建文件夾
get_archive_formats()
功能:獲取當前系統已註冊的歸檔文件格式(後綴) 格式:shutil.get_archive_formats() 返回值:列表 [(後綴,解釋),(後綴,解釋),(後綴,解釋)...]
get_unpack_formats()
功能:獲取當前系統已經註冊的解包文件格式(後綴) 格式:shutil.get_unpack_formats() 返回值:列表 [(後綴,解釋),(後綴,解釋),(後綴,解釋)...]
paramiko
paramiko是一個用於作遠程控制的模塊,使用該模塊能夠對遠程服務器進行命令或文件操做,值得一說的是,fabric和ansible內部的遠程管理就是使用的paramiko來現實。
一、下載安裝
1
2
3
|
pycrypto,因爲 paramiko 模塊內部依賴pycrypto,因此先下載安裝pycrypto
pip3 install pycrypto
pip3 install paramiko
|
二、模塊使用
#!/usr/bin/env python #coding:utf-8 import paramiko ssh = paramiko.SSHClient() ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) ssh.connect('192.168.1.108', 22, 'alex', '123') stdin, stdout, stderr = ssh.exec_command('df') print stdout.read() ssh.close();
import paramiko private_key_path = '/home/auto/.ssh/id_rsa' key = paramiko.RSAKey.from_private_key_file(private_key_path) ssh = paramiko.SSHClient() ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) ssh.connect('主機名 ', 端口, '用戶名', key) stdin, stdout, stderr = ssh.exec_command('df') print stdout.read() ssh.close()
import os,sys import paramiko t = paramiko.Transport(('182.92.219.86',22)) t.connect(username='wupeiqi',password='123') sftp = paramiko.SFTPClient.from_transport(t) sftp.put('/tmp/test.py','/tmp/test.py') t.close() import os,sys import paramiko t = paramiko.Transport(('182.92.219.86',22)) t.connect(username='wupeiqi',password='123') sftp = paramiko.SFTPClient.from_transport(t) sftp.get('/tmp/test.py','/tmp/test2.py') t.close()
import paramiko pravie_key_path = '/home/auto/.ssh/id_rsa' key = paramiko.RSAKey.from_private_key_file(pravie_key_path) t = paramiko.Transport(('182.92.219.86',22)) t.connect(username='wupeiqi',pkey=key) sftp = paramiko.SFTPClient.from_transport(t) sftp.put('/tmp/test3.py','/tmp/test3.py') t.close() import paramiko pravie_key_path = '/home/auto/.ssh/id_rsa' key = paramiko.RSAKey.from_private_key_file(pravie_key_path) t = paramiko.Transport(('182.92.219.86',22)) t.connect(username='wupeiqi',pkey=key) sftp = paramiko.SFTPClient.from_transport(t) sftp.get('/tmp/test3.py','/tmp/test4.py') t.close()
requests
Python標準庫中提供了:urllib等模塊以供Http請求,可是,它的 API 太渣了。它是爲另外一個時代、另外一個互聯網所建立的。它須要巨量的工做,甚至包括各類方法覆蓋,來完成最簡單的任務。
import urllib.request f = urllib.request.urlopen('http://www.webxml.com.cn//webservices/qqOnlineWebService.asmx/qqCheckOnline?qqCode=424662508') result = f.read().decode('utf-8')
import urllib.request req = urllib.request.Request('http://www.example.com/') req.add_header('Referer', 'http://www.python.org/') r = urllib.request.urlopen(req) result = f.read().decode('utf-8')
注:更多見Python官方文檔:https://docs.python.org/3.5/library/urllib.request.html#module-urllib.request
Requests 是使用 Apache2 Licensed 許可證的 基於Python開發的HTTP 庫,其在Python內置模塊的基礎上進行了高度的封裝,從而使得Pythoner進行網絡請求時,變得美好了許多,使用Requests能夠垂手可得的完成瀏覽器可有的任何操做。
一、安裝模塊
1
|
pip3 install requests
|
二、使用模塊
# 一、無參數實例 import requests ret = requests.get('https://github.com/timeline.json') print(ret.url) print(ret.text) # 二、有參數實例 import requests payload = {'key1': 'value1', 'key2': 'value2'} ret = requests.get("http://httpbin.org/get", params=payload) print(ret.url) print(ret.text)
# 一、基本POST實例 import requests payload = {'key1': 'value1', 'key2': 'value2'} ret = requests.post("http://httpbin.org/post", data=payload) print(ret.text) # 二、發送請求頭和數據實例 import requests import json url = 'https://api.github.com/some/endpoint' payload = {'some': 'data'} headers = {'content-type': 'application/json'} ret = requests.post(url, data=json.dumps(payload), headers=headers) print(ret.text) print(ret.cookies)
requests.get(url, params=None, **kwargs)
requests.post(url, data=None, json=None, **kwargs) requests.put(url, data=None, **kwargs) requests.head(url, **kwargs) requests.delete(url, **kwargs) requests.patch(url, data=None, **kwargs) requests.options(url, **kwargs) # 以上方法均是在此方法的基礎上構建 requests.request(method, url, **kwargs)
更多requests模塊相關的文檔見:http://cn.python-requests.org/zh_CN/latest/
三、Http請求和XML實例
實例:檢測QQ帳號是否在線
import urllib import requests from xml.etree import ElementTree as ET # 使用內置模塊urllib發送HTTP請求,或者XML格式內容 """ f = urllib.request.urlopen('http://www.webxml.com.cn//webservices/qqOnlineWebService.asmx/qqCheckOnline?qqCode=424662508') result = f.read().decode('utf-8') """ # 使用第三方模塊requests發送HTTP請求,或者XML格式內容 r = requests.get('http://www.webxml.com.cn//webservices/qqOnlineWebService.asmx/qqCheckOnline?qqCode=424662508') result = r.text # 解析XML格式內容 node = ET.XML(result) # 獲取內容 if node.text == "Y": print("在線") else: print("離線")
實例:查看火車停靠信息
import urllib import requests from xml.etree import ElementTree as ET # 使用內置模塊urllib發送HTTP請求,或者XML格式內容 """ f = urllib.request.urlopen('http://www.webxml.com.cn/WebServices/TrainTimeWebService.asmx/getDetailInfoByTrainCode?TrainCode=G666&UserID=') result = f.read().decode('utf-8') """ # 使用第三方模塊requests發送HTTP請求,或者XML格式內容 r = requests.get('http://www.webxml.com.cn/WebServices/TrainTimeWebService.asmx/getDetailInfoByTrainCode?TrainCode=G666&UserID=') result = r.text # 解析XML格式內容 root = ET.XML(result) for node in root.iter('TrainDetailInfo'): print(node.find('TrainStation').text,node.find('StartTime').text,node.tag,node.attrib)
注:更多接口猛擊這裏
paramiko模塊
import paramiko # 建立SSH對象 ssh = paramiko.SSHClient() # 容許鏈接不在known_hosts文件上的主機 ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) # 鏈接服務器 ssh.connect(hostname="192.168.0.99", port=22, username="root", password="rootroot") # 執行命令 stdin, stdout, stderr = ssh.exec_command('df') # 獲取結果 result = stdout.read().decode() # 獲取錯誤提示(stdout、stderr只會輸出其中一個) err = stderr.read() # 關閉鏈接 ssh.close() print(stdin, result, err)
注:若是註釋「ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())」這句,會報錯。
相似問題能夠爲linux系統中~/.ssh/known_hosts文件中的內容。
2、實現SFTP功能
import paramiko # 鏈接虛擬機centos上的ip及端口 transport = paramiko.Transport(("192.168.0.99", 22)) transport.connect(username="root", password="rootroot") # 將實例化的Transport做爲參數傳入SFTPClient中 sftp = paramiko.SFTPClient.from_transport(transport) # 將「calculator.py」上傳到filelist文件夾中 sftp.put('D:\python庫\Python_shell\day05\calculator.py', '/filelist/calculator.py') # 將centos中的aaa.txt文件下載到桌面 sftp.get('/filedir/aaa.txt', r'C:\Users\duany_000\Desktop\test_aaa.txt') transport.close()
注:若是遇到Windows中路徑問題,連接以下網址http://blog.csdn.net/elang6962/article/details/68068126
3、使用祕鑰實現SSH功能
import paramiko private_key = paramiko.RSAKey.from_private_key_file('id_rsa31') # 建立SSH對象 ssh = paramiko.SSHClient() ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) # 鏈接服務器 ssh.connect(hostname='192.168.79.9', port=22, username='root', pkey=private_key) stdin, stdout, stderr = ssh.exec_command('ifconfig') res_out = stdout.read() print(res_out.decode()) ssh.close()
4、使用祕鑰實現SFTP功能
import paramiko private_key = paramiko.RSAKey.from_private_key_file('id_rsa31') # 鏈接虛擬機centos上的ip及端口 transport = paramiko.Transport(("192.168.79.9", 22)) transport.connect(username="root", pkey=private_key) # 將實例化的Transport做爲參數傳入SFTPClient中 sftp = paramiko.SFTPClient.from_transport(transport) # 將「calculator.py」上傳到filelist文件夾中 sftp.put('D:\python庫\Python_shell\day05\calculator.py', '/filedir/calculator.py') # 將centos中的aaa.txt文件下載到桌面 sftp.get('/filedir/oldtext.txt', r'C:\Users\duany_000\Desktop\oldtext.txt') transport.close()