time、random以及序列化模块
一、 time模塊
在Python中,通常有這幾種方式來表示時間:
- 時間戳(timestamp):通常來說,時間戳表示的是從1970年1月1日00:00:00開始按秒計算的偏移量。我們運行“type(time.time())”,返回的是float類型。
- 格式化的時間字符串(Format String)
- 結構化的時間(struct_time):struct_time元組共有9個元素共九個元素:(年,月,日,時,分,秒,一年中第幾周,一年中第幾天,夏令時),可以通過點來調用具體里面的值。 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 當前時區的名稱 相應參數?
-
? ? 其中計算機認識的時間只能是'時間戳'格式,而程序員可處理的或者說人類能看懂的時間有: '格式化的時間字符串','結構化的時間'?,于是有了下圖的轉換關系
- 結構化的時間(struct_time):struct_time元組共有9個元素共九個元素:(年,月,日,時,分,秒,一年中第幾周,一年中第幾天,夏令時),可以通過點來調用具體里面的值。 import time
#--------------------------我們先以當前時間為準,讓大家快速認識三種形式的時間
print(time.time()) # 時間戳:1487130156.419527
?結合上圖可得:
#--------------------------按圖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) 3、mktime(t) : 將一個struct_time轉化為時間戳。
print(time.mktime(time.localtime())) #1473525749.0 4、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 # 5、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- 格式化時間
?
?
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)) 當前推后30天?
?
?
含有月份周期的時間表示:
?
?結合上圖可得:
#--------------------------按圖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) # 結構化時間調用里面的參數 結構化時間點功能?補充:
1、time.clock():這個需要注意,在不同的系統上含義不同。在UNIX系統上,它返回的是“進程時間”,它是用秒表示的浮點數(時間戳)。而在WINDOWS中,第一次調用,返回的是進程運行的實際時間。而第二次之后的調用是自第一次調用以后到現在的運行時間。(實際上是以WIN32上QueryPerformanceCounter()為基礎,它比毫秒表示更為精確)也就是CPU工作時間。
2、time.sleep(secs):線程推遲指定的時間運行。單位為秒
?二、datetime模塊
#時間加減 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)
?
?三、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 ?
?
?四、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)的第二個元素 BaiduNetdiskDownloadprint(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[, οnerrοr=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 walk函數的使用?
?五、sys模塊
? sys是與Python解釋器交互
1、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 syssys.argv # 命令行參數List,第一個元素是程序本身路徑sys.exit(n) # 退出程序,正常退出時exit(0) n 為其他數時,都存在其他異常退出,顯示1print(sys.version) # 獲取Python解釋程序的版本信息 # sys.maxint # 最大的Int值print(sys.path ) # 返回模塊的搜索路徑,初始化時使用PYTHONPATH環境變量的值 會查找環境變量,當然最開始是從就近的工作文件找sys.path.append() # 可以添加查找給出的絕對目錄,添加到列表中 print(sys.platform) # 返回操作系統平臺名稱 # win32 或則 linuxsys.stdout.write('#') # 向終端打印標準化輸出 print就是用這個方法做出來的
sys.moudles # 是一個全局字典,該字典是python啟動后就加載在內存中。每當程序員導入新的模塊,sys.modules將自動記錄該模塊
?進度條打印實例:
import sys import time import randomdef 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 randomdef 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)1、 *values : 表示要打印的值 表示任何多個無名參數, 各個值之間用‘,’(逗號隔開),打印出來各個值之間用空格隔開2、sep=’ ‘: 表示當輸入多個打印的值時,各個值之間分割方式, 默認空格,可以自定義例:print('a','m','c',sep='\n') # a m c 換行3、 end=‘\n’**: 控制print中傳入值輸出完后結束符號,默認換行,這里可以設置為其他,如 ‘\t’, ’ ’ 等等, 可以自己定義例:print('python', end=' ')print('is good') # python is good4、file=sys.stdout:設置輸出設備,及把print中的值打印到什么地方,默認輸出到準端,可以設置file= 文件儲存對象,把內容存到該文件中例:f = open(r'a.txt', 'w')print('python is good', file=f)f.close()# 則把python is good保存到 a.txt 文件中5、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 中
?
六、序列化模塊json、pickle、shelve簡述
什么叫序列化——將由原來的字典、列表等內容轉換成一個字符串的過程就叫做序列化,反序列化就是將字符串或則字節轉化成原先的數據類型。
序列化的目的;
1、以某種存儲形式使自定義對象持久化;
2、將對象從一個地方傳遞到另一個地方;
3、使程序更具有維護.
# 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模塊
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=Falseimport 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=Falseimport 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反序列化 主要用于一個數據直接存在文件里—— 直接和文件打交道
?
?
八、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類型的,區別于jsondump寫入文件 文件模式必須是帶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=nameself.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=nameself.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?
將對象反序列時,必須保證該對象的類必須存在,否則讀取報錯
再次打開注釋,執行以下,就正常了
?
九、shelve模塊
?Shelve是對象持久化保存方法,將對象保存到文件里面,缺省(即默認)的數據存儲文件是二進制的。可以作為一個簡單的數據存儲方案。
注意shelve模塊中的key鍵必須是字符串形式,value可以是任意值。會同時打開三個文件。
使用方法:
1、shelve.open(filename, flag=’c’, protocol=None, writeback=False):? ? ? 創建或打開一個shelve對象。shelve默認打開方式支持同時讀寫操作。
filename是關聯的文件路徑。可選參數flag:
1、默認為‘c’:如果數據文件不存在,就創建,允許讀寫;可以是: ‘r’: 只讀;’w’: 可讀寫;
2、可以為‘n’: 每次調用open()都重新創建一個空的文件,可讀寫。
protocol:是序列化模式,默認值為None。具體還沒有嘗試過,從pickle的資料中查到以下信息【protocol的值可以是1或2,表示以二進制的形式序列化】
2、shelve.close()? ? ? #?同步并關閉shelve對象,注意每次使用完畢后都要關閉shelve對象,同樣可以使用with語句。
with shelve.open('spam') as db:db['eggs'] = 'eggs' with語句3、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()就可以了,然后我們可以像使用字典一樣來使用這個shelfimport 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模塊代碼示例?
總結:
1、shelve模塊比pickle模塊簡單,只有一個open函數,返回類似字典的對象,可讀可寫;2、key必須為字符串,而值可以是python所支持的數據類型3、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()
?
轉載于:https://www.cnblogs.com/double-W/p/9599232.html
總結
以上是生活随笔為你收集整理的time、random以及序列化模块的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 各种标志位的含义
- 下一篇: ldap配置系列二:jenkins集成l