python3练习题:11-20
practice11: excel讀寫(xlsx文件)
1、 excel讀
excel內容
import xlrd#不可以使用~來代替/home/openlab book = xlrd.open_workbook('/home/openlab/Desktop/test.xls') #一個book含有兩張sheet,可以看到返回了兩個sheet object print(book.sheets()) #取到book里的第一張sheet sheet0 = book.sheet_by_index(0) #查看sheet的行 print(sheet0.nrows) #查看sheet的列 print(sheet0.ncols) #訪問cell,即一個小格 #返回類型+value print(sheet0.cell(0,0)) #返回類型 1代表文本 2代表數字 print(sheet0.cell(0,0).ctype) print(sheet0.cell(1,1).ctype) #返回value print(sheet0.cell(0,0).value) #訪sheet的行,行號從0開始 print(sheet0.row(1)) #訪sheet的行,并對選中的行按列切片 row_values(行號,起始列號,終止列號=None) 注意:左閉右開 print(sheet0.row_values(1,1,None)) print(sheet0.col(0)) print(sheet0.col_values(0,1,None)) #增加或修改一個cell print(sheet0.cell(1,1)) sheet0.put_cell(1,1,2,100,None) print(sheet0.cell(1,1))結果:
2、 Excel 寫
import xlwt#構造book wbook = xlwt.Workbook() sheet1 = wbook.add_sheet('sheet1') #write(行,列,值) sheet1.write(0,0,'kesjsjjs') #保存 wbook.save('/home/openlab/Desktop/111.xls')3、 小結
- xlrd僅能把xls文件讀取為book對象,進行操作;xlwt僅能創建book對象,寫入值后,將其寫入為一個xls文件;二者都圍繞book對象進行操作
- xlwt構造的sheet不包含put_cell方法!!只有讀出來的sheet才有
- 一般處理過程:用xlrd讀excel,用put-cell修改sheet,再把修改過的sheet賦值給xlwt的sheet,最后保存
4、 實例:求和
import xlrd,xlwt #讀取excel文件 rbook = xlrd.open_workbook('grades.xls') #讀取sheet表 rsheet = rbook.sheet_by_index(0) cols = rsheet.ncols #修改sheet表 rsheet.put_cell(0,cols,1,'總分',None) for row in range(1,rsheet.nrows):grade = sum(rsheet.row_values(row,1))rsheet.put_cell(row,cols,2,grade,None)wbook = xlwt.Workbook() #創建一張臨時表,暫時為空 wsheet = wbook.add_sheet('sheet1') #將修改過得rsheet賦值給臨時表 for r in range(rsheet.nrows):for c in range(rsheet.ncols):wsheet.write(r,c,rsheet.cell(r,c).value)wbook.save('grades1.xls')5、 實例,比較兩張表的差異!
import xlrdclass Compare_sheets():def __init__(self,sheet1,sheet2):self.sheet1 = sheet1self.sheet2 = sheet2def __sheet_to_set(self,sheet):tmpset = set()for row in range(1,sheet.nrows):info_tuple = tuple(sheet.row_values(row))tmpset.add(info_tuple)return tmpsetdef __compare_sets(self,set1,set2):print("sheet1中不同與sheet2的元素有:",set1-set2)print("sheet2中不同與sheet1的元素有:",set2-set1)def go(self):set1 = self.__sheet_to_set(self.sheet1)set2 = self.__sheet_to_set(self.sheet2)self.__compare_sets(set1,set2)rbook = xlrd.open_workbook('id.xls') sheet1 = rbook.sheet_by_index(0) sheet2 = rbook.sheet_by_index(1) compare = Compare_sheets(sheet1,sheet2) compare.go()#practice12:csv文件處理
csv文件格式
- 基本單位為一行,行與行之間以\n分割
- 每一行由多個基本元素組成,元素與元素之間以逗號分割
csv文件的讀寫:調用模塊csv(reader和writer)
#practice13:文本文件讀寫
1、 文本文件與二進制文件區別
- 定義
計算機的存儲在物理上是二進制的,所以文本文件與二進制文件的區別并不是物理上的,而是邏輯上的。這兩者只是在編碼層次上有差異。
簡單來說,文本文件是基于字符編碼的文件,常見的編碼有ASCII編碼,UNICODE編碼等等。二進制文件是基于值編碼的文件,如音頻文件,冠字號文件,你可以根據具體應用,指定某個值(可以看作是自定義編碼)。
從上面可以看出文本文件基本上是定長編碼的(也有非定長的編碼如UTF-8),基于字符,每個字符在具體編碼中是固定的,ASCII碼是8個比特的編碼,UNICODE一般占16個比特。而二進制文件可看成是變長編碼的,因為是值編碼,多少個比特代表一個值,完全由自己決定。
+ 存取
文本工具打開一個文件,首先讀取文件物理上所對應的二進制比特流,然后按照所選擇的解碼方式來解釋這個流,然后將解釋結果顯示出來。一般來說,你選取的解碼方式會是ASCII碼形式(ASCII碼的一個字符是8個比特),接下來,它8個比特8個比特地來解釋這個文件流。記事本無論打開什么文件都按既定的字符編碼工作(如ASCII碼),所以當他打開二進制文件時,出現亂碼也是很必然的一件事情了,解碼和譯碼不對應。
文本文件的存儲與其讀取基本上是個逆過程。而二進制文件的存取與文本文件的存取差不多,只是編/解碼方式不同而已。
+ 優缺點
因為文本文件與二進制文件的區別僅僅是編碼上不同,所以他們的優缺點就是編碼的優缺點。一般認為,文本文件編碼基于字符定長,譯碼容易;二進制文件編碼是變長的,所以它靈活,存儲利用率要高些,譯碼難一些(不同的二進制文件格式,有不同的譯碼方式)。
在windows下,文本文件不一定是ASCII來存貯的,因為ASCII碼只能表示128的標識,打開一個txt文檔,然后另存為,有個選項是編碼,可以選擇存貯格式,一般來說UTF-8編碼格式兼容性要好一些。而二進制用的計算機原始語言,不存貯兼容性
+ 注意
如果一個文件內存儲了一堆隨機二進制數字,可以視作二進制文件,但由于未對其編解碼進行定義,該二進制文件是沒有意義的
2、文本文件操作
2.1 讀文本文件
#以文本方式打開文件,t默認;但如果要指明編解碼方式,必須用關鍵字來指明參數,而不是位置參數 #rf為可迭代對象。每次迭代返回一行,返回值為字符串 with open('pingan.csv','rt',encoding='GB2312') as rf:text = rf.read()#文本模式下,讀到的內容為strprint(type(text))#看下只讀+文本模式下,文件對象有哪些方法print(dir(rf))#查看文件對象有無寫權限print(rf.writable())#返回當前文件指針的位置,單位byte;35689正好代表文件的大小print(rf.tell())#調整指針位置函數seek(offset,from_what=0)#定位到文件開始rf.seek(0)#查看當前指針位置print(rf.tell())#指針定位到文件尾rf.seek(0,2)#在文本文件中做如下隨意定位指針的做法非常危險!不推薦rf.seek(10)print(rf.tell())#按行讀取(\n),返回結果為字符串rf.seek(0)print(rf.readline())#讀取文件為列表,列表每個元素為文本中的一行,列表每個元素為字符串mylist = rf.readlines()print(mylist)文本模式下,read/readline/readlines都沒有參數
2.2 寫文本文件
with open('write.txt','wt',encoding='utf8')as wf:#write參數是str,返回值為寫入的byte數print(wf.write('wakaka服裝店'))#查看方法print(dir(wf))#tell、seek可以使用,不推薦print(wf.tell())wf.seek(0)print(wf.tell())3、 編解碼格式解讀
3.1 概念
- 一般有:ascll GB2312 gbk utf-8(unicode的一種)
- GB2312 gbk用于漢字,兼容ascll
- utf-8是一種通用編碼,適用于多種語言,同樣兼容ascll碼
- python中有str和byte兩種字符串,用print輸出byte字符串時,操作系統或者IDE會自動將byte中的字母、數字、控制符通過ascll解碼出來(因為所有編碼方式對于字母、數字、控制符的編碼都是相同的,即兼容ascll碼)
- str本質是文本;bytes本質是o和1組成的串
3.2 實踐str、byte與編解碼
#str轉bytes:僅含有ascll碼的字符 a = r'123abc\n' print(a) print(type(a)) b = b'123abc\n' print(b) print(type(b)) #str轉bytes:含有非ascll碼,此時要借助類bytes #bytes中表示數字、字母、控制符(ascll字符)的比特會被IDE自動解碼 a = '123abc呵呵' print(bytes(a,encoding='utf-8')) print(bytes(a,encoding='gbk')) #gbk向下兼容GB2312 print(bytes(a,encoding='GB2312')) #str轉bytes:含有非ascll碼,此時要借助str的encode方法 print(a.encode(encoding='utf-8')) print(a.encode(encoding='GBK'))#bytes轉str b = b'123abc\xe5\x91\xb5\xe5\x91\xb5' print(b.decode('utf-8')) #對于ascll碼字符集組成的字符串,直接字符表示即可,不必要寫其十六進制值 b = b'\x33\x30' print(b.decode('utf-8')) b = b'30' print(b.decode('utf-8'))4、 集中文件打開模式總結:a w+ a+ r+
#文本附加模式:在源文件末添加文本 #說明write.txt初始文本為:xxxxxxxxxx with open('write.txt','at',encoding='utf-8') as f:print(f.readable())print(f.writable())f.write('cacacac')with open('write.txt','r',encoding='utf-8') as rf:print(rf.read())#文本讀寫w+t:該模式下寫會將源文件內容擦掉并寫入新內容 with open('write.txt','w+t',encoding='utf-8') as f:#指針位于文件首print(f.tell())#原始內容被擦掉,所以內容為空print(f.read())f.write('xxxxxxxxxx')f.seek(0)print(f.read())#文本讀寫a+t:該模式下初始指針位于文件尾,讀寫均要注意指針位置 with open('write.txt','a+t',encoding='utf-8') as f:f.write('aaa')#指針位于文件尾,讀取為空print(f.read())f.seek(0)print(f.read())#文本讀寫r+t:初始指針位于文件頭,源文件內容未擦除,進行覆蓋寫;讀的話嚴格按照指針位置進行讀 with open('write.txt','r+t',encoding='utf-8') as f:f.write('AAAAAAAA')print(f.tell())print(f.read())#practice14:二進制文件讀寫
1、 對于byte字符串的認識以及誤區
注意:byte字符串每次iteration,返回值為一個二進制數,IDE會自動將數字進行ascll解碼
2、 二進制結構化數據的讀取與寫入:方法一
import struct #二進制結構化數據的寫入與讀取 #寫入方法一: bytes1 = struct.pack('<5shhc','ab我'.encode('utf-8'),10,15,b'q') #注意:5s表示5byte的字符串;h:short;i:int;c:char;這些都是c語言的概念,字符串與字符char必須是bytes類型 #對應打包關系:‘ab我’:ab\xe6\x88\x91,字符'我'z占后三個byte #10:\n\x00,因為short占兩個byte,且存儲方式默認為little ending(小頭),所以真實比特流為\x00\n -> \x00\x0A -> ob0000000000001010 -> 10 print(bytes1) #讀取方法一: text = struct.unpack('<5shhc',bytes1) print(text)struct模塊作用:This module performs conversions between Python values and C structs represented as Python bytes objects.
3、 二進制結構化數據的讀取與寫入:方法二
from struct import Struct mystruct = Struct('<5shhc') bytes1 = mystruct.pack('ab我'.encode('utf-8'),10,15,b'q') print(bytes1) tuple1 = mystruct.unpack(bytes1) print(tuple1)struct.pack操作不同于encode操作:前者針對python內的所有value,包括字符串(pack處理時以字符為基本單位)、int、float等;encode僅僅針對文本,即字符串;相同點:最終轉換值為bytes對象
4、 注意點
- linux與windowas系統下都默認byte order為little ending,即字節存儲順序為倒序:如占4個byte的int類型\x00\x00\x00\xff,在計算機中存儲時,4個byte順序正好倒過來:\xff\x00\x00\x00
- 字符串處理時,以每個字符為基本單位,一個字符占一個字節,不存在字節順序的問題!(中文字符待考證)
- <表示little ending,如果不標,默認為@,會造成數據大小隨平臺而變的情況,容易出大坑!
- 最好寫fmt(格式字符串)時,開頭標注’<’
5、 二進制wav文件讀寫實例
5.1 文件格式
import struct from collections import namedtuple import arrayclass Wav():def __init__(self,filename,filename_tosave):#雖然在類的其他方法里創建self.avariable也會生成實例屬性,但最好把多個方法公用的實例屬性放在__init__里定義self.filename = filenameself.filename_tosave = filename_tosave#由于python弱類型,這里用數字0初始化也沒問題,但最好還是用空bytes比較規整self.head_bytes = b''self.myarray = array.array('h')self.myarray_length = 0def __parse(self):'''二進制數據讀取為結構化bytes'''with open(self.filename,'rb') as rf:self.head_bytes = rf.read(44)rf.seek(0,2)self.myarray_length = int((rf.tell()-44)/2)self.myarray = array.array('h',(0 for _ in range(self.myarray_length)))rf.seek(44,0)rf.readinto(self.myarray)def __print_header(self):'''把header由bytes轉化為Python數據類型并輸出'''Header = namedtuple('Header','NumChanels SampleRate BitsPerSample')numchanels = struct.unpack('<h',self.head_bytes[22:24])samplerate = struct.unpack('<i',self.head_bytes[24:28])bitespersample = struct.unpack('<h',self.head_bytes[34:36])header = Header(numchanels,samplerate,bitespersample)#打印具名元組print(header)def __modify_wav(self):'''將wav文件音量調低'''for i in range(self.myarray_length):self.myarray[i] = int(self.myarray[i]/10)def __save(self):'''將修改的文件保存'''with open(self.filename_tosave,'wb') as wf:wf.write(self.head_bytes)self.myarray.tofile(wf)def go(self):#啟動程序self.__parse()self.__print_header()self.__modify_wav()self.__save()wav = Wav('1969.wav','demo1.wav') wav.go()#practice15:json模塊學習
1、 json.dumps與json.loads(針對json字符串與python對象的轉換,s表示string)
import jsonjson_string = '[1,2,"abc",{"hello":3,"world":2}]' python_obj = json.loads(json_string) print(python_obj) print(type(python_obj))python_obj = {'hello':[1,2,3],'works':18} json_string = json.dumps(python_obj) print(json_string) print(type(json_string))2、 json.dump與json.load(針對json文件與python對象的轉換)
import jsonpython_obj = {'hello':[1,2,3],'works':18}#將python數據結構轉化為json文件 with open('demo.json','w') as wf:json.dump(python_obj,wf)#從json文件中讀取json字符串 with open('demo.json','r') as rf:#對于文本模式讀取,返回值定為字符串,這里返回json字符串text = rf.read()print(type(text))print(text)#json字符串反序列化為python數據結構python1 = json.loads(text)print(type(python1))print(python1)with open('demo.json','r') as rf:#省略中間過程,json文件直接轉換為python數據結構python2 = json.load(rf)print(type(python2))print(python2)從上圖可以看出json文件與json字符串的關系:存儲json格式數據的文件叫做json文件,json文件內并不存儲雙引號;json文件被讀取后,read方法自動返回字符串(json字符串);所以json格式的數據在程序內表現形式為字符串,在文件內表現為正常的文本文件。
#practice16:XML文件的解析與創建
1、解析xml文檔
1.1 預先準備的xml文件
<?xml version="1.0"?> <data><country name="liechtenstein"><rank updated="yes">5</rank><year>2008</year><gdp>141100</gdp></country><country name="china"><rank updated="yes">2</rank><year>2010</year><gdp>1422000</gdp></country><country name="american"><rank updated="no">1</rank><year>2010</year><gdp>3122000</gdp></country> </data>1.2 解析xml文檔的基本操作
from xml.etree.ElementTree import parsewith open('demo.xml','r') as rf:#返回ElementTree對象et = parse(rf) #獲取根節點,返回Element對象 root = et.getroot() print(root) #獲取某個Element對象的標簽、屬性以及文本 print(root.tag) print(root.attrib) print(root.text) #獲取某個element對象的直接子元素,返回值為element對象 print(root.getchildren()) #element對象自身可迭代 for child in root:#get函數返回element object 對應的attribute(‘name')的值,get獲取元素屬性值print(child.get('name')) #find與findall一般用法默認查找直接子元素 print(root.find('country')) print(root.findall('country')) print(root.iterfind('country')) for ele in root.iterfind('country'):print(ele) #iter方法用來生成某個element下所有子元素的迭代器(包括非直接子元素) print(list(root.iter())) #指定元素的tag print(list(root.iter('rank')))上述方法的標簽參數均使用當前位置,借助xpath的語法可以操作任意位置的元素
from xml.etree.ElementTree import parsewith open('demo.xml','r') as rf: et = parse(rf) root = et.getroot() print(root.findall('rank')) #.代表當前元素,即root節點;//代表當前節點下所有子節點(包括非直接節點) print(root.findall('.//rank')) #..表示當前元素的父元素;/類似于Linux print(root.findall('.//rank/..')) #*代表所有直接子元素 print(root.findall('*/gdp')) #帶屬性的元素 print(root.findall('country[@name]')) print(root.findall('country[@name="china"]')) #任然要指明路徑 print(root.findall('rank[@updated]')) print(root.findall('.//rank[@updated]')) #包含某個直接子元素的元素(不支持非直接元素) print(root.findall('country[rank]')) #element[childelement="text"],text即便是數字也要加引號 print(root.findall('country[rank="1"]')) #findall找到的多個元素可以使用位置參數取出來 print(root.findall('country[rank][1]')) print(root.findall('country[rank][2]')) print(root.findall('country[rank][last()]')) print(root.findall('country[rank][last()-1]')) #注意:text文本都是string,即便看到是數字,讀取后還需要進一步處理轉換。 print(type(root.find('.//rank[@updated="no"]').text))附錄:支持的xpath語法
2、使用python數據結構創建xml
2.1 xml創建操作
from xml.etree.ElementTree import Element,ElementTree,tostring#創建一個元素 e = Element('data',{'name':"wakak"}) #tostring函數以字符串的形式展現整個元素 print(tostring(e)) #修改或增加元素屬性,注意屬性必須是字符串 e.set('age','18') e.set('name','wahahah') print(tostring(e)) #修改或增加元素的text,xml是個文本文件,所以數字也要用字符串的形式寫入 e.text = "123.0" print(tostring(e)) #創建父子關系 e1 = Element('row') e1.text = "row1" e2 = Element('hello') e2.text = 'hello world' e1.append(e2) e.append(e1) print(tostring(e)) #創建elementTree et = ElementTree(e) et.write("demo1.xml")tostring默認為byte字符串
2.2 csv文件轉xml文件實例
#csv轉xml import csv from xml.etree.ElementTree import Element,ElementTreedef csv_to_string(filename):with open(filename,'rt',encoding='utf-8') as rf:reader = csv.reader(rf)header = next(reader)root = Element('data')#下面的寫法可以避免獲取csv文件的行數!!for row in reader:#可以看出row可迭代!迭代返回值為list,可迭代:print(type(row))e = Element('row')root.append(e)#用到了zip函數+元組拆包#同樣避免了計算行長度for tag,text in zip(header,row):e1 = Element(tag)e1.text = texte.append(e1)et = ElementTree(root)return et et = csv_to_string('pingan.csv') #此處必須表明編碼格式,若省略,默認us-ascll !!!,解析會亂碼 et.write('demo2.xml',encoding='utf-8')#practice17:設置文件緩沖
1、行緩沖(只用于文本模式)
2、 全緩沖
只有二進制模式下,buffering參數才生效;文本模式下buffering采用默認值io.DEFAULT_BUFFER_SIZE,linux下為8192
當湊滿2049byte后,前2048byte才被真正寫入文件
3、 無緩沖(只用于二進制模式)
#practice18:二進制文件映射到內存
優點:為了隨機訪問文件的內容,使用 mmap 將文件映射到內存中是一個高效和優雅的方
法。例如,你無需打開一個文件并執行大量的 seek() , read() , write() 調用,只需
要簡單的映射文件并使用切片操作訪問數據即可。
#practice19:訪問文件狀態
1、 獲取文件狀態(3種方法)
import os #調用系統stat函數,對于link文件,針對其源文件調用函數 s = os.stat('demo.txt') #返回os.stat_result對象 print(s) print(type(s))#調用系統lstat函數,對于link文件,針對當前的文件名調用函數 s = os.lstat('demo.txt') #返回os.stat_result對象 print(s) print(type(s))#調用系統fstat函數,該函數的參數必須為打開的文件描述符 with open('demo.txt') as f:s = os.fstat(f.fileno())#返回os.stat_result對象print(s)print(type(s))2、 os.stat_result對象的十大屬性(常用如下)
- st_mode:文件模式,包括文件類型與權限
- st_uid:user ID
- st_gid:group ID
- st_size:文件大小byte
- st_atime:最后打開時間
- st_ctime:最后修改時間
3、 stat模塊的使用(負責翻譯os.stat_result對象)
import os import stat import times = os.stat('demo.txt') print(s) #輸出文件mode print(s.st_mode) #使mode可讀 print(stat.filemode(s.st_mode)) #判斷文件類型 print(stat.S_ISDIR(s.st_mode)) print(stat.S_ISREG(s.st_mode)) print(stat.S_ISLNK(s.st_mode))#判斷文件權限 #判斷文件屬主是否有讀權限;結果非空->True.結果為0,False; print(s.st_mode & stat.S_IRUSR) print(s.st_mode & stat.S_IXUSR)#文件訪問、修改時間 #返回結構化時間對象,細粒度 print(time.localtime(s.st_mtime)) #返回時間字符串! print(time.asctime(time.localtime(s.st_atime)))#獲取文件大小,byte print(s.st_size)4、 用OS.path模塊實現stat中的部分功能(不涉及文件權限,推薦用此方法)
import os.path import time#os.path內的函數內部調用os.stat 來獲取文件狀態,所以使用時可省略這一步! #判斷文件類型 print(os.path.isdir('demo.txt')) print(os.path.islink('demo.txt')) print(os.path.isfile('demo.txt'))#判斷文件大小 print(os.path.getsize('demo.txt'))#判斷修改,打開時間 print(os.path.getmtime('demo.txt')) print(time.asctime(time.localtime(os.path.getatime('demo.txt'))))os.path模塊不包含處理文件權限的函數
#practice20:使用臨時文件存儲內存數據
1、 兩個類的基本用法
from tempfile import TemporaryFile,NamedTemporaryFile import tempfile #臨時文件的默認存放地 print(tempfile.gettempdir())#創造臨時文件來存儲大的數據,避免數據空耗內存;mode一般選取w+b 或 w+t #temporary創建的臨時文件在/tmp中也找不到 #返回文件對象! f = TemporaryFile(mode='w+t') f.write('#'*1000000) f.close() #使用namedtemporary創建帶名字的臨時文件,該文件在/tmp中找得到 #返回類文件對象 f1 = NamedTemporaryFile(mode='w+t') print(f1.name) f1.write('%'*10000) #使用delete后,臨時文件關閉后,文件不被立即刪除 f2 = NamedTemporaryFile(mode='w+t',delete=False) print(f2.name) f2.write('%'*1000) #這個地方不好驗證,最好還是使用python控制臺來驗證臨時文件的創建過程與差別2、使用python控制臺來驗證temporaryfile與namedtemporaryfile
總結
以上是生活随笔為你收集整理的python3练习题:11-20的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: sublime3(anaconda) 无
- 下一篇: python3练习题:并发编程(21-2