在Python中,一般有這幾種方式來表示時間:python
import time #--------------------------咱們先以當前時間爲準,讓你們快速認識三種形式的時間 print(time.time()) # 時間戳:1487130156.419527
f = time.localtime(time.time() - 86000 * 3) # 150000000 秒 86000,三天前的結構化時間 print(time.strftime("%Y-%m-%d %X")) #格式化的時間字符串:'2017-02-15 11:40:53',當前字符串時間,
print(time.strftime('%Y-%m-%d %H:%M:%S',f)) # f是結構化時間 將結構化時間轉化爲字符串時間 print(time.localtime()) #本地時區的struct_time print(time.gmtime()) #UTC時區的struct_time
%y 兩位數的年份表示(00-99) %Y 四位數的年份表示(000-9999) %m 月份(01-12) %d 月內中的一天(0-31) %H 24小時制小時數(0-23) %I 12小時制小時數(01-12) %M 分鐘數(00=59) %S 秒(00-59) %a 本地簡化星期名稱 %A 本地完整星期名稱 %b 本地簡化的月份名稱 %B 本地完整的月份名稱 %c 本地相應的日期表示和時間表示 %j 年內的一天(001-366) %p 本地A.M.或P.M.的等價符 %U 一年中的星期數(00-53)星期天爲星期的開始 %w 星期(0-6),星期天爲星期的開始 %W 一年中的星期數(00-53)星期一爲星期的開始 %x 本地相應的日期表示 %X 本地相應的時間表示 %Z 當前時區的名稱
其中計算機認識的時間只能是'時間戳'格式,而程序員可處理的或者說人類能看懂的時間有: '格式化的時間字符串','結構化的時間' ,因而有了下圖的轉換關係mysql
結合上圖可得:linux
#--------------------------按圖1轉換時間 1、localtime([secs])將一個時間戳轉換爲當前時區的struct_time。secs參數未提供,則以當前時間爲準。
time.localtime() # time.struct_time(tm_year=2018, tm_mon=9, tm_mday=6, tm_hour=20, tm_min=56, tm_sec=16, tm_wday=3, tm_yday=249, tm_isdst=0) 當前時間
time.localtime(1473525444.037215) # time.struct_time(tm_year=2016, tm_mon=9, tm_mday=11, tm_hour=0, tm_min=37, tm_sec=24, tm_wday=6, tm_yday=255, tm_isdst=0) 給定時間的格式化時間
2、gmtime([secs]) 和localtime()方法相似,gmtime()方法是將一個時間戳轉換爲UTC時區(0時區)的struct_time。
time.gmtime() # 結果 time.struct_time(tm_year=2011, tm_mon=5, tm_mday=5, tm_hour=6, tm_min=19,tm_sec=48, tm_wday=3, tm_yday=125, tm_isdst=0)
三、mktime(t) : 將一個struct_time轉化爲時間戳。
print(time.mktime(time.localtime())) #1473525749.0
四、strftime(format[, t]) : 把一個表明時間的元組或者struct_time(如由time.localtime()和time.gmtime()返回)轉化爲格式化的時間字符串。若是t未指定,將傳入time.localtime()。
#若是元組中任何一個元素越界,ValueError的錯誤將會被拋出。 print(time.strftime("%Y-%m-%d %X", time.localtime())) #2016-09-11 00:49:56
print(time.strftime('%Y--%m--%d %X',)) #2018--09--06 21:04:16
# 五、time.strptime(string[, format]) # 把一個格式化時間字符串轉化爲struct_time。實際上它和strftime()是逆操做。
print(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默認爲:"%a %b %d %H:%M:%S %Y"。
總結:
time是datetime的底層模塊
時間戳時間-localtime/gmtime-> 結構化時間 -strftime-> 格式化時間
時間戳時間<-mktime- 結構化時間 <-strptime- 格式化時間程序員
time.time() # 獲取時間戳
時間戳 --localtime('時間戳')--> 結構化時間 結構化時間--mktime('結構化時間')--> 時間戳 結構化時間--strftime('格式','結構化時間')--> 結構化的字符串 # 能夠格式自定義,
結構化字符串時間 --strptime('結構化時間','格式')--> 結構化時間 # 必須參數一一對應
1、當前年月日的凌晨12點對應的時間戳時間是多少 today =time.strftime('%Y-%m-%d') # 格式化時間 locals_time=time.strptime(today,'%Y-%m-%d') # 獲取到結構化時間,默認返回凌晨時間 print(time.mktime(locals_time)) # 獲取時間戳 today =time.strftime('%Y-%m-%d %X') # 格式化時間 locals_time=time.strptime(today,'%Y-%m-%d %X') # 獲取到結構化時間,默認返回當前時間 print(time.mktime(locals_time)) # 獲取時間戳 print(time.time())
例題: 1、將s時間往前推30天 import time s = '2019-03-20 10:40:00' local_time = time.strptime(s,'%Y-%m-%d %X') # 轉化成結構化時間 print(local_time) #time.struct_time(tm_year=2019, tm_mon=3, tm_mday=20, tm_hour=10, tm_min=40, tm_sec=0, tm_wday =2, tm_yday=79, tm_isdst=-1) x=time.mktime(local_time)+30 * 86000 # 轉化成時間戳 new_time = time.localtime(x) #將時間戳轉化爲結構化時間 print(new_time) new_time_local =time.strftime('%Y-%m-%d %X',new_time) # 將結構化時間轉化爲字符串格式 print(new_time_local) #準確答案 import datetime #將當前時間推前30天 print(datetime.datetime.now()-datetime.timedelta(30))
含有月份週期的時間表示:web
結合上圖可得:sql
#--------------------------按圖2轉換時間 # asctime([t]) : 把一個表示時間的元組或者struct_time表示爲這種形式:'Sun Jun 20 23:21:05 1993'。 # 若是沒有參數,將會將time.localtime()做爲參數傳入。 print(time.asctime())#Sun Sep 11 00:43:43 2016 # ctime([secs]) : 把一個時間戳(按秒計算的浮點數)轉化爲time.asctime()的形式。若是參數未給或者爲 # None的時候,將會默認time.time()爲參數。它的做用至關於time.asctime(time.localtime(secs))。 print(time.ctime()) # Sun Sep 11 00:46:38 2016 print(time.ctime(time.time())) # Sun Sep 11 00:46:38 2016
輸入某年某月某日,判斷是這一年中的第幾天?(用內置模塊實現) import time input_ = input('請輸入年月日:') time_local = time.strptime(input_,'%Y-%m-%d %X') print(time_local.tm_yday) # 結構化時間調用裏面的參數
補充:shell
一、time.clock():這個須要注意,在不一樣的系統上含義不一樣。在UNIX系統上,它返回的是「進程時間」,它是用秒錶示的浮點數(時間戳)。而在WINDOWS中,第一次調用,返回的是進程運行的實際時間。而第二次以後的調用是自第一次調用之後到如今的運行時間。(其實是以WIN32上QueryPerformanceCounter()爲基礎,它比毫秒錶示更爲精確)也就是CPU工做時間。數據庫
二、time.sleep(secs):線程推遲指定的時間運行。單位爲秒編程
2、datetime模塊json
#時間加減 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)) #時間替換 2018-09-07 02:03:37.591115 其實就是修改時間
import datetime
t = datetime.datetime.now() # 時間操做符獲取對象
print(t.date()) # 就能夠訪問具體的天數
print(t.time())
print(t.timestamp()) #時間戳
print(t.day)
print(t.month)
from datetime import datetime,timedelta # 從xx導入 建議 print(datetime.now() - timedelta(3)) # 進行加減天數
3、random模塊
import random print(random.random()) #(0,1)----float 大於0且小於1之間的小數 print(random.randint(1,3)) #[1,3] 大於等於1且小於等於3之間的整數 print(random.randrange(1,3)) #[1,3) 大於等於1且小於3之間的整數 print(random.choice([1,'23',[4,5]])) #1或者23或者[4,5],這裏能夠填字符串,在字符串中隨機一個字母
print(random.choices([1,'23',[4,5],'3','4'],k=3)) #['4', '23', '23'],隨機3個
print(random.sample([1,'23',[4,5]],2)) #列表元素任意2個組合 print(random.uniform(1,3)) #大於1小於3的小數,如1.927109612082716 item=[1,3,5,7,9] random.shuffle(item) #打亂item的順序,至關於"洗牌" print(item)
例: 驗證碼生成器:
import random
def make_code(n):
res = ''
for i in range(n):
s1 = chr(random.randint(65,90)) # 生成字母chr
s2 = str(random.randint(0,9))
res += random.choice([s1,s2])
return res
print(make_code(9)) # H53FVG8K4
4、os模塊
os模塊是與操做系統交互的一個接口
import os print(os.getcwd()) # 獲取當前工做目錄,即當前python腳本工做的目錄路徑 D:\pycharm code\離校\時間模塊
os.chdir("D:\pycharm code\day2") # 改變當前腳本工做目錄;至關於shell下cd
print(os.getcwd()) # D:\pycharm code\day2 當再一次判斷位置時,發生了變化
# print(os.curdir) # . # print(os.pardir) # ..
# os.makedirs('abc\\alex') # 在day2(當前工做目錄)下生成abc文件,在abc下再生成alex文件 # os.makedirs('dirname1/dirname2') # 可生成多層遞歸目錄 (已存在的文件名不能再一次生成)
#os.removedirs('dirname1/dirname2') # 若目錄爲空,則刪除,並遞歸到上一級目錄,如若也爲空,則刪除,依此類推
# os.mkdir('dirname') # 生成單級目錄;至關於shell中mkdir dirname # os.rmdir('dirname') # 刪除單級空目錄,若目錄不爲空則沒法刪除,報錯;至關於shell中rmdir dirname
#print(os.listdir('.')) # 列出指定目錄下的全部文件和子目錄,包括隱藏文件,並以列表方式打印,['abc', '今日大綱', '做業講解.py']
# os.remove('哈哈哈') # 刪除一個文件 # os.rename("abc","newname") # 重命名文件/目錄 舊名字,新名字
print(os.stat('./newname')) # 獲取文件目錄信息('path/filename') os.stat_result(st_mode=16895, st_ino=2533274790436658, # st_dev=2092381065,st_nlink=1, st_uid=0, st_gid=0, st_size=0, st_atime=1536304047, st_mtime=1536300456,st_ctime=1536300456)
s = os.stat('./newname') print(s.st_size) # 可打印文件大小
print(os.sep) # 輸出操做系統特定的路徑分隔符,win下爲"\\",Linux下爲"/"
s=os.linesep # 輸出當前平臺使用的行終止符,win下爲"\r\n",Linux下爲"\n",Mac下爲 '\r'
print('c,jjj%s'%s,end=' ') print('哈哈') print(os.pathsep) # 輸出用於分割文件路徑的字符串 win下爲;,Linux下爲:
print(os.name) # 輸出字符串指示當前使用平臺。win->'nt'; Linux->'posix'
#os.system("ping www.baidu.com -t") # 運行shell命令,直接顯示,cmd窗口 # print(os.environ) # 獲取系統環境變量 # print(os.path.abspath('D:\BaiduNetdiskDownload')) # 返回path規範化的絕對路徑
print(os.path.split('D:\BaiduNetdiskDownload')) # 將path分割成目錄和文件名二元組返回 ('D:\\', 'BaiduNetdiskDownload')
print(os.path.dirname('D:\BaiduNetdiskDownload')) # 返回path的目錄。其實就是os.path.split(path)的第一個元素 D:\
print(os.path.basename('D:\BaiduNetdiskDownload')) # 返回path最後的文件名。如何path以/或\結尾,那麼就會返回空值。 # 即os.path.split(path)的第二個元素 BaiduNetdiskDownload
print(os.path.exists('D:\BaiduNetdiskDownload')) # 若是path存在,返回True;若是path不存在,返回False True
print(os.path.isabs('D:\BaiduNetdiskDownload')) # 若是path是絕對路徑,返回True True
print(os.path.isfile('D:\BaiduNetdiskDownload')) # 若是path是一個存在的文件,返回True。不然返回False False
print(os.path.isdir('D:\BaiduNetdiskDownload')) # 若是path是一個存在的目錄,則返回True。不然返回False True
#os.path.join(path1[, path2[, ...]]) # 將多個路徑組合後返回,第一個絕對路徑以前的參數將被忽略
print(os.path.join('/my/','name/is/','vampire_techking')) # /my/name/is/vampire_techking,注意這裏的第二個參數不能以/開頭
print(os.path.getatime('D:\BaiduNetdiskDownload')) # 返回path所指向的文件或者目錄的最後存取時間 1536305083.0908828
print(os.path.getmtime('D:\BaiduNetdiskDownload')) # 返回path所指向的文件或者目錄的最後修改時間
print(os.path.getsize('D:\BaiduNetdiskDownload')) # 返回path的大小
簡要總結:
os.path.abspath(path) #返回絕對路徑 os.path.basename(path) #返回文件名 os.path.commonprefix(list) #返回list(多個路徑)中,全部path共有的最長的路徑。 os.path.dirname(path) #返回文件路徑 os.path.exists(path) #路徑存在則返回True,路徑損壞返回False os.path.expanduser(path) #把path中包含的"~"和"~user"轉換成用戶目錄 os.path.expandvars(path) #根據環境變量的值替換path中包含的」$name」和」${name}」 os.path.getatime(path) #返回最後一次進入此path的時間。 os.path.getmtime(path) #返回在此path下最後一次修改的時間。 os.path.getctime(path) #返回path的大小 os.path.getsize(path) #返回文件大小,若是文件不存在就返回錯誤 os.path.isabs(path) #判斷是否爲絕對路徑 os.path.isfile(path) #判斷路徑是否爲文件 os.path.isdir(path) #判斷路徑是否爲目錄 os.path.islink(path) #判斷路徑是否爲連接 os.path.ismount(path) #判斷路徑是否爲掛載點() os.path.join(path1[, path2[, ...]]) #把目錄和文件名合成一個路徑 os.path.normcase(path) #轉換path的大小寫和斜槓 os.path.normpath(path) #規範path字符串形式 os.path.realpath(path) #返回path的真實路徑 os.path.relpath(path[, start]) #從start開始計算相對路徑 os.path.samefile(path1, path2) #判斷目錄或文件是否相同 os.path.sameopenfile(fp1, fp2) #判斷fp1和fp2是否指向同一文件 os.path.samestat(stat1, stat2) #判斷stat tuple stat1和stat2是否指向同一個文件 os.path.split(path) #把路徑分割成dirname和basename,返回一個元組 os.path.splitdrive(path) #通常用在windows下,返回驅動器名和路徑組成的元組 os.path.splitext(path) #分割路徑,返回路徑名和文件擴展名的元組 os.path.splitunc(path) #把路徑分割爲加載點與文件 os.path.walk(path, visit, arg) #遍歷path,進入每一個目錄都調用visit函數,visit函數必須有 3個參數(arg, dirname, names),dirname表示當前目錄的目錄名,names表明當前目錄下的全部文件名,args則爲walk的第三個參數 os.path.supports_unicode_filenames #設置是否支持unicode路徑名 在Linux和Mac平臺上,該函數會原樣返回path,在windows平臺上會將路徑中全部字符轉換爲小寫,並將全部斜槓轉換爲飯斜槓。 >>> os.path.normcase('c:/windows\\system32\\') 'c:\\windows\\system32\\' 規範化路徑,如..和/ >>> os.path.normpath('c://windows\\System32\\../Temp/') 'c:\\windows\\Temp' >>> a='/Users/jieli/test1/\\\a1/\\\\aa.py/../..' >>> print(os.path.normpath(a)) /Users/jieli/test1
1、os.walk() 方法用於經過在目錄樹中游走輸出在目錄中的文件名,向上或者向下。 格式:os.walk(top[, topdown=True[, onerror=None[, followlinks=False]]]) top -- 是你所要遍歷的目錄的地址, 返回的是一個三元組(root,dirs,files)。 root 所指的是當前正在遍歷的這個文件夾的自己的地址 dirs 是一個 list ,內容是該文件夾中全部的目錄的名字(不包括子目錄) files 一樣是 list , 內容是該文件夾中全部的文件(不包括子目錄) topdown --可選,爲 True,則優先遍歷 top 目錄,不然優先遍歷 top 的子目錄 (默認爲開啓)。若是 topdown 參數爲 True,walk 會遍歷top文件夾,與top 文件夾中每個子目錄。 onerror -- 可選,須要一個 callable 對象,當 walk 須要異常時,會調用。 followlinks -- 可選,若是爲 True,則會遍歷目錄下的快捷方式(linux 下是軟鏈接 symbolic link )實際所指的目錄(默認關閉),若是爲 False,則優先遍歷 top 的子目錄。 import os for root, dirs, files in os.walk(".", topdown=False): for name in files: print(os.path.join(root, name)) for name in dirs: print(os.path.join(root, name)) 運行結果: ./.bash_logout ./amrood.tar.gz ./.emacs ./httpd.conf ./www.tar.gz ./mysql.tar.gz ./test.py ./.bashrc ./.bash_history ./.bash_profile ./tmp ./tmp/test.py
5、sys模塊
sys是與Python解釋器交互
一、sys.argv 命令行參數List,第一個元素是程序自己路徑
這個time.py文件的內容以下:
不難看出這個程序,把咱們在外部傳入的post傳入在這個sys.argv中且是個列表,固然傳入的參數個數任意多。
對其進行改進!
import sys # print(sys.argv) def updata(): print('上傳!!!') def download(): print('download……') if sys.argv[1] == 'post': updata() elif sys.argv[1] =='download': download()
結果:
import sys sys.argv # 命令行參數List,第一個元素是程序自己路徑sys.exit(n) # 退出程序,正常退出時exit(0) n 爲其餘數時,都存在其餘異常退出,顯示1 print(sys.version) # 獲取Python解釋程序的版本信息 # sys.maxint # 最大的Int值 print(sys.path ) # 返回模塊的搜索路徑,初始化時使用PYTHONPATH環境變量的值 會查找環境變量,固然最開始是從就近的工做文件找sys.path.append() # 能夠添加查找給出的絕對目錄,添加到列表中 print(sys.platform) # 返回操做系統平臺名稱 # win32 或則 linux
sys.stdout.write('#') # 向終端打印標準化輸出 print就是用這個方法作出來的
sys.moudles # 是一個全局字典,該字典是python啓動後就加載在內存中。每當程序員導入新的模塊,將自動記錄該模塊
sys.modules
進度條打印實例:
import sys import time import random def progress(percent, width=50): if percent >= 1: percent = 1 # 百分比保證100% show_str = ('[%%-%ds]'%width)%(int(width*percent)*'#') print('\r%s %d%%'%(show_str,int(100*percent)),file=sys.stdout,flush=True,end='') data_size = 1025 recv_size = 0 while recv_size < data_size: s = random.random() time.sleep(s) # 模擬數據的傳輸延遲 recv_size += 50 # 每次收1024 percent = recv_size/data_size # 接收的比例 progress(percent,width=70)import sys import time import random def progress(percent, width=50): if percent >= 1: percent = 1 # 百分比保證100% show_str = ('[%%-%ds]'%width)%(int(width*percent)*'#') print('\r%s %d%%'%(show_str,int(100*percent)),file=sys.stdout,flush=True,end='') data_size = 1025 recv_size = 0 while recv_size < data_size: s = random.random() time.sleep(s) # 模擬數據的傳輸延遲 recv_size += 50 # 每次收1024 percent = recv_size/data_size # 接收的比例 progress(percent,width=70)
補充print知識點:
print()函數的參數以下:
print(*values, sep=' ', end='\n', file=sys.stdout, flush=False)
一、 *values : 表示要打印的值
表示任何多個無名參數, 各個值之間用‘,’(逗號隔開),打印出來各個值之間用空格隔開
二、sep=’ ‘: 表示當輸入多個打印的值時,各個值之間分割方式, 默認空格,能夠自定義
例:print('a','m','c',sep='\n') # a m c 換行
三、 end=‘\n’**: 控制print中傳入值輸出完後結束符號,默認換行,這裏能夠設置爲其餘,如 ‘\t’, ’ ’ 等等, 能夠本身定義
例:print('python', end=' ')
print('is good') # python is good
四、file=sys.stdout:設置輸出設備,及把print中的值打印到什麼地方,默認輸出到準端,能夠設置file= 文件儲存對象,把內容存到該文件中
例:f = open(r'a.txt', 'w')
print('python is good', file=f)
f.close()
# 則把python is good保存到 a.txt 文件中
五、flush=False: 該參數主要是刷新, 默認False,不刷新,Ture時刷新,例如在上面 4 中print中設置:
f = open(r'a.txt', 'w')
print('python is good', file=f, flush=True) # print到f中的內容先從到內存中,
當文件對象關閉時才把內容輸出到 a.txt 中,當flush=True時它會當即把內容刷新存到 a.txt 中
什麼叫序列化——將由原來的字典、列表等內容轉換成一個字符串的過程就叫作序列化,反序列化就是將字符串或則字節轉化成原先的數據類型。
序列化的目的;
一、以某種存儲形式使自定義對象持久化;
二、將對象從一個地方傳遞到另外一個地方;
三、使程序更具備維護.
# a發送以一個數據給b,因爲發送數據,必須是二進制。因此須要經歷編碼到解碼的過程 dic = {'a':(1,2,3)} s = str(dic).encode(encoding='utf-8') # 編碼 ret = s.decode(encoding='utf-8') # 解碼 print(ret) # 查看數據 print(type(ret)) # 查看類型 print(type(eval(ret))) # 還原爲字典 eval將字符串轉換爲字典 # 結果: {'a': (1, 2, 3)} <class 'str'> <class 'dict'> 使用eval不安全,有多是病毒,接收方,啪的一些,就執行了。 這個時候,就須要用到序列化了
如上圖,可知:
dic --> 字符串 序列化
字符串 --> dic 反序列化
序列化 == 創造一個序列 ==》 創造一個字符串
實例化 == 創造一個實例
在Python中的序列化模塊:
json 全部的編程語言都通用的序列化格式
它支持的數據類型很是有限 數字 字符串 列表 字典。
pickle 只能在python語言的程序之間傳遞數據用的
pickle支持python中全部的數據類型。
shelve python3.* 以後纔有的,能夠把它看成字典處理。
Json模塊提供四個功能:dumps、dump、loads、load,除了能夠序列化字典還能夠序列化列表等。注意Json操做的是字符串,因此在打開讀寫文件的時候使用‘w'和’r‘模式。
序列化(dumps,dump)
import json # 導入模塊 dic = {"慕容美雪":(170,60,'賞花')} # 鍵必須加雙引號 ret = json.dumps(dic) # 序列化 print(type(dic),dic) # 查看原始數據類型 print(type(ret),ret) # 查看序列化後的數據 <class 'dict'> {'慕容美雪': (170, 60, '賞花')} <class 'str'> {"\u6155\u5bb9\u7f8e\u96ea": [170, 60, "\u8d4f\u82b1"]} 從結果中,能夠看出: 原始數據類型是字典,序列化以後,就是字符串類型。並且中文變成了看不懂的字符串。 這是由於json.dumps 序列化時對中文默認使用的ascii編碼。 想輸出真正的中文須要指定ensure_ascii=False import json # 導入模塊 dic = {"慕容美雪":(170,60,'賞花')} ret = json.dumps(dic,ensure_ascii=False) # 序列化時,不使用ascii碼 print(type(dic),dic) # 查看原始數據類型 print(type(ret),ret) # 查看序列化後的數據 <class 'dict'> {'慕容美雪': (170, 60, '賞花')} <class 'str'> {"慕容美雪": [170, 60, "賞花"]} 因爲json不識別元組,json認爲元組和列表是一回事,因此變成了列表。 在json中,引號,統一使用雙引號
反序列化 (loads,load)
import json # 導入模塊 dic = {"慕容美雪":(170,60,'賞花')} ret = json.dumps(dic,ensure_ascii=False) # 序列化時,不使用ascii碼 res = json.loads(ret) # 反序列化 print(type(res),res) # 查看反序列化後的數據 執行輸出: <class 'dict'> {'慕容美雪': [170, 60, '賞花']} 從結果中,能夠看出,原來的單引號由還原回來了。 反序列化,比eval要安全。因此eval儘可能少用。
注意: dump和load是直接將對象序列化以後寫入文件,且依賴一個文件句柄。而dumps和loads是直接在文件中進行操做,固然能夠能夠經過文件的‘w'模式寫入。
dump 將序列化內容寫入文件 import json # 導入模塊 dic = {"慕容美雪":(170,60,'賞花')} f = open('美雪','w',encoding='utf-8') json.dump(dic,f) # 先接收要序列化的對象,再接收文件句柄 f.close() 執行程序,查看文件美雪內容爲: {"\u6155\u5bb9\u7f8e\u96ea": [170, 60, "\u8d4f\u82b1"]} 要想文件寫入中文,能夠加參數ensure_ascii=False import json # 導入模塊 dic = {"慕容美雪":(170,60,'賞花')} f = open('美雪','w',encoding='utf-8') json.dump(dic,f,ensure_ascii=False) # 先接收要序列化的對象,再接收文件句柄 f.close() 執行程序,再次查看文件內容: {"慕容美雪": [170, 60, "賞花"]}
load 讀取文件中的序列化內容 import json # 導入模塊 dic = {"慕容美雪":(170,60,'賞花')} f = open('美雪','r',encoding='utf-8') ret = json.load(f) #接收文件句柄 print(ret) # 查看內容 print(type(ret)) # 查看變量類型 f.close() # 最後記得關閉文件句柄 執行輸出: {'慕容美雪': [170, 60, '賞花']} <class 'dict'>
其餘參數:
import json data = {'username':['李華','二愣子'],'sex':'male','age':16} json_dic2 = json.dumps(data,sort_keys=True,indent=4,separators=(',',':'),ensure_ascii=False) print(json_dic2) 執行輸出: { "age":16, "sex":"male", "username":[ "李華", "二愣子" ] } 參數說明: Skipkeys:默認值是False,若是dict的keys內的數據不是python的基本類型(str,unicode,int,long,float,bool,None),設置爲False時,就會報TypeError的錯誤。此時設置成True,則會跳過這類key ensure_ascii:,當它爲True的時候,全部非ASCII碼字符顯示爲\uXXXX序列,只需在dump時將ensure_ascii設置爲False便可,此時存入json的中文便可正常顯示。) indent:應該是一個非負的整型,若是是0就是頂格分行顯示,若是爲空就是一行最緊湊顯示,不然會換行且按照indent的數值顯示前面的空白分行顯示,這樣打印出來的json數據也叫pretty-printed json separators:分隔符,其實是(item_separator, dict_separator)的一個元組,默認的就是(',’,’:’);這表示dictionary內keys之間用","隔開,而KEY和value之間用":"隔開。 sort_keys:將數據根據keys的值進行排序。
寫入多行
import json dic1 = {"S":(170,60,'唱歌')} dic2 = {"H":(170,60,'唱歌')} dic3 = {"E":(170,60,'唱歌')} f = open('she','a',encoding='utf-8') f.write(json.dumps(dic1)+'\n') # 寫入一行內容,注意,必定要加換行符 f.write(json.dumps(dic2)+'\n') f.write(json.dumps(dic3)+'\n') f.close() # 關閉文件句柄 執行程序,查看文件she內容: {"S": [170, 60, "\u5531\u6b4c"]} {"H": [170, 60, "\u5531\u6b4c"]} {"E": [170, 60, "\u5531\u6b4c"]}
讀取多行
import json f = open('she','r',encoding='utf-8') for i in f: print(json.loads(i.strip())) f.close() 執行輸出: {'S': [170, 60, '唱歌']} {'H': [170, 60, '唱歌']} {'E': [170, 60, '唱歌']}
總結:
dumps序列化 loads反序列化 只在內存中操做數據 主要用於網絡傳輸 和多個數據與文件打交道
dump序列化 load反序列化 主要用於一個數據直接存在文件裏—— 直接和文件打交道
8、Pickle模塊
用於Python特有的類型和Python的數據類型間進行轉換 。 pickle模塊提供了四個功能:dumps、dump(序列化,存)、loads(反序列化,讀)、load(不只能夠序列化字典、列表……還能夠把Python中任意的數據類型序列化)
用法和json是同樣的 : 注意的是Pickle模塊是基於字節操做,因此在讀寫的時候要用’wb‘和’rb'
dumps序列化:
import pickle dic = {(170,60,'唱歌'):"S"} print(pickle.dumps(dic)) #執行結果: b'\x80\x03}q\x00K\xaaK<X\x06\x00\x00\x00\xe5\x94\xb1\xe6\xad\x8cq\x01\x87q\x02X\x01\x00\x00\x00Sq\x03s.' 輸出結果是bytes類型的,區別於json dump寫入文件 文件模式必須是帶b,由於它是bytes類型、 import pickle dic = {(170,60,'唱歌'):"S"} f = open('s','wb') #使用dump必須以+b的形式打開文件,編碼不須要指定,由於是bytes類型 pickle.dump(dic,f) f.close() # 注意要關閉文件句柄 #執行結果是一堆亂碼
load 讀取文件內容:
import pickle f = open('s','rb') # bytes類型不須要指定編碼 print(pickle.load(f)) f.close() # 注意要關閉文件句柄 執行結果: {(170, 60, '唱歌'): 'S'}
dump寫入多行內容和load讀取文件內容:
import pickle dic1 = {"張靚穎":(170,60,'唱歌')} dic2 = {"張韶涵":(170,60,'唱歌')} dic3 = {"梁靜茹":(170,60,'唱歌')} f = open('singer','wb') pickle.dump(dic1,f) pickle.dump(dic2,f) pickle.dump(dic3,f) f.close() #執行結果是一堆亂碼 load 讀取文件內容 import pickle f = open('singer','rb') print(pickle.load(f)) print(pickle.load(f)) print(pickle.load(f)) print(pickle.load(f)) # 多讀取一行,就會報錯 f.close()
可是輸出的結果以下
爲了解決這個問題,須要用到while循環+try:
import pickle f = open('singer','rb') while True: try: print(pickle.load(f)) except Exception: # 接收一切錯誤 break # 跳出循環 f.close() 執行結果: {'張靚穎': (170, 60, '唱歌')} {'張韶涵': (170, 60, '唱歌')} {'梁靜茹': (170, 60, '唱歌')}
總結:
json 在寫入屢次dump的時候 不能對應執行屢次load來取出數據,pickle能夠
json 若是要寫入多個元素 能夠先將元素dumps序列化,f.write(序列化+'\n')寫入文件
讀出元素的時候,應該先按行讀文件,在使用loads將讀出來的字符串轉換成對應的數據類型
注意:pickle還能夠序列化一些類或者函數(json不能):
import pickle class A: def __init__(self,name,age): self.name=name self.age=age a = A('alex',80) ret = pickle.dumps(a) # 序列化對象 print(ret) obj = pickle.loads(ret) # 反序列化 print(obj.__dict__) # 查看對象屬性<br>f.close() 執行結果: b'\x80\x03c__main__\nA\nq\x00)\x81q\x01}q\x02(X\x04\x00\x00\x00nameq\x03X\x04\x00\x00\x00alexq\x04X\x03\x00\x00\x00ageq\x05KPub.' {'name': 'alex', 'age': 80} 將對象a寫入文件: import pickle class A: def __init__(self,name,age): self.name=name self.age=age a = A('alex',80) f = open('a','wb') obj = pickle.dump(a,f) f.close() 執行結果: 也是一堆亂碼
假設是一款Python遊戲,就能夠將人物的屬性,寫入文件。再次登錄時,就能夠從新加載了,用pickle就比較方便了。
當刪除一個類的時候(註釋代碼),再次讀取文件,就會報錯
import pickle # class A: # def __init__(self,name,age): # self.name=name # self.age=age # a = A('alex',80) f = open('a','rb') obj = pickle.load(f) print(obj.__dict__) f.close() 執行報錯 AttributeError: Can't get attribute 'A' on <module '__main__' from 'E:/python_script/day25/test.py'> 提示找不到類A
將對象反序列時,必須保證該對象的類必須存在,不然讀取報錯
再次打開註釋,執行如下,就正常了
9、shelve模塊
Shelve是對象持久化保存方法,將對象保存到文件裏面,缺省(即默認)的數據存儲文件是二進制的。能夠做爲一個簡單的數據存儲方案。
注意shelve模塊中的key鍵必須是字符串形式,value能夠是任意值。會同時打開三個文件。
使用方法:
一、shelve.open(filename, flag=’c’, protocol=None, writeback=False): 建立或打開一個shelve對象。shelve默認打開方式支持同時讀寫操做。
filename是關聯的文件路徑。
可選參數flag:
一、默認爲‘c’:若是數據文件不存在,就建立,容許讀寫;能夠是: ‘r’: 只讀;’w’: 可讀寫;
二、能夠爲‘n’: 每次調用open()都從新建立一個空的文件,可讀寫。
protocol:是序列化模式,默認值爲None。具體尚未嘗試過,從pickle的資料中查到如下信息【protocol的值能夠是1或2,表示以二進制的形式序列化】
二、shelve.close() # 同步並關閉shelve對象,注意每次使用完畢後都要關閉shelve對象,一樣可使用with語句。
with shelve.open('spam') as db: db['eggs'] = 'eggs'
三、writeback:默認爲False。當設置爲True之後,shelf將會將全部從DB中讀取的對象存放到一個內存緩存。
當咱們close()打開的shelf的時候,緩存中全部的對象會被從新寫入DB。writeback方式有優勢也有缺點(減小出錯率,可是會增長內存開銷)。
代碼示範:
# 1.建立一個shelf對象,直接使用open函數便可 import shelve s = shelve.open('test_shelf.db') # try: s['kk'] = {'int': 10, 'float': 9.5, 'String': 'Sample data'} s['MM'] = [1, 2, 3] finally: s.close() # 2.若是想要再次訪問這個shelf,只須要再次shelve.open()就能夠了,而後咱們能夠像使用字典同樣來使用這個shelf import shelve try: s = shelve.open('test_shelf.db') value = s['kk'] print(value) finally: s.close() # 3.對shelf對象,增、刪、改操做 import shelve s = shelve.open('test_shelf.db', flag='w', writeback=True) try: # 增長 s['QQQ'] = 2333 # 刪除 del s['MM'] # 修改 s['kk'] = {'String': 'day day up'} finally: s.close() # 注意:flag設置爲‘r’-只讀模式,當程序試圖去修改一個以只讀方式打開的DB時,將會拋一個訪問錯誤的異常。異常的具體類型取決於anydbm這個模塊在建立DB時所選用的DB。異常舉例:anydbm.error: need ‘c’ or ‘n’ flag to open new db # 4.循環遍歷shelf對象 import shelve s = shelve.open('test_shelf.db') try: # 方法一: for item in s.items(): print ('鍵[{}] = 值[{}]'.format(item[0], s[item[0]])) # 方法二: for key, value in s.items(): print(key, value) finally: s.close() # 5.備註一個錯誤: # open中的參數filename,起初認爲須要手動新建一個.db,或者.dat的文件,目前電腦中無任何真正的數據庫文件,因此採用了新建txt文件,修改後綴的方法建立.db,或者.dat的文件。 # 解釋器報錯,提示內容爲:"anydbm.error: db type could not be determined", # 緣由是是filename已經存在,而且格式與shelve不符,因此提示 「db type could not be determined」。 # 解決方法是,刪除該文件。首次運行後會自動生成該filename文件。 # 6.稍微複雜些的案例,實現一個簡單提問式的數據庫
總結:
一、shelve模塊比pickle模塊簡單,只有一個open函數,返回相似字典的對象,可讀可寫;
二、key必須爲字符串,而值能夠是python所支持的數據類型
三、shelve模塊(**)------能夠當作數據庫用,之後基本不會用,(能夠很方面的往文件中寫數據類型和讀)
import shelve #存取很方便(能夠作一個簡單的數據存儲方案) f=shelve.open(r'sheve.txt') f['stu1_info']={'name':'egon','age':18,'hobby':['piao','smoking','drinking']} #存 f['stu2_info']={'name':'gangdan','age':53} f['school_info']={'website':'http://www.pypy.org','city':'beijing'} print(f['stu1_info']['hobby']) f.close() import shelve d=shelve.open(r'a.txt') #生成三個文件分別是:a.txt.bak\a.txt.dat\a.txt.dir d['tom']={'age':18,'sex':'male'} #存的時候會生成三個文件,不用管,是python的一種處理機制 print(d['tom']['sex']) #能夠取出字典中的key對應的value print(d['tom']) #取出tom對應的字典 d.close() import shelve d=shelve.open(r'a.txt',writeback=True) #writeback=True,對子字典修改完後要寫回,不然不會看到修改後的結果 d['egon']={'age':18,'sex':'male'} #存的時候會生成三個文件,不用管,是python的一種處理機制 d['egon']['age']=20 #將年齡修改成20 print(d['egon']['age']) #此時拿到的是修改後的年齡 print(d['egon']['sex']) d.close()