sys模塊
這是一個跟python解釋器關系密切的標准庫。它提供了一些和python解釋器操作密切的屬性和函數。
sys中常用的函數和屬性:
sys.argv:
sys.argv是專門用來向python解釋器傳遞參數的,稱為“命令行參數”。它的返回值是一個列表,列表中的元素依次是文件名、參數1、參數2……
macdeMacBook-Pro:~ mac$ python3 test.py ['test.py'] macdeMacBook-Pro:~ mac$ python3 test.py aa bb cc # 參數之間用空格隔開 ['test.py', 'aa', 'bb', 'cc'] # 文件名和參數的列表
sys.exit():
這個方法的作用是退出當前程序。
Help on built-in function exit in module sys:
exit(...)
exit([status])
Exit the interpreter by raising SystemExit(status).
If the status is omitted or None, it defaults to zero (i.e., success).
If the status is an integer, it will be used as the system exit status.
If it is another kind of object, it will be printed and the system
exit status will be one (i.e., failure).
在大多數函數中會用到return,其含義是終止當前的函數,並向調用位置返回相應值。而sys.exit()的含義是退出當前程序(不僅僅是退出當前函數),並發起SystemExit異常。如果使用sys.exit(0)表示正常退出;如果在退出的是需要打印一些內容,則可以使用sys.exit('我退出啦!')的形式,即向exit()方法中傳入字符串參數。
import sys for i in range(5): if i == 3: sys.exit(0) # 正常退出 else: print(i, end=' ') python3 test.py # 執行文件 0 1 2 for i in range(5): if i == 3: sys.exit('aaaaa') # 退出並打印提示信息 else: print(i, end=' ') python3 test.py # 執行文件 0 1 2 aaaaa # 提示信息也被打印出來了
sys.path:
它可以查找模塊所在的目錄,以列表的形式顯示出來。用append()方法,能夠向這個列表增加新的模塊目錄。
>>> import sys >>> print(sys.path) ['', '/Library/Frameworks/Python.framework/Versions/3.7/lib/python37.zip', '/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7', '/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/lib-dynload', '/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages']
copy模塊
這個模塊中常用的就是copy和deepcopy兩個方法。copy是淺拷貝,deepcopy是深拷貝。
os模塊
os模塊是與操作系統交互的一個接口。
操作命令:
os.getcwd():獲取當前工作目錄,即當前python腳本工作的路徑。 os.chdir("dirname"):改變當前腳本工作目錄,相當於shell下cd。 os.curdir:返回當前目錄: ('.')。 os.pardir:獲取當前目錄的父目錄字符串名:('..')。 os.makedirs('dirname1/dirname2'):遞歸生成多層目錄。 os.removedirs('dirname1'):若目錄為空,則刪除,並遞歸到上一級目錄,若也為空,則刪除,依此類推。若目錄不為空,則不刪除。 os.mkdir('dirname'):生成單級目錄。 os.rmdir('dirname'):刪除單級空目錄,若目錄不為空則無法刪除,報錯。 os.listdir('dirname'):列出指定目錄下的所有文件和子目錄,包括隱藏文件,並以列表方式打印。 os.remove():刪除一個文件。 os.rename("oldname","newname"):重命名文件/目錄。 os.stat('path/filename'):獲取文件/目錄信息。 os.sep:輸出操作系統特定的路徑分隔符,win下為"\\",Linux下為"/"。 os.linesep:輸出當前平台使用的行終止符,win下為"\t\n",Linux下為"\n"。 os.pathsep:輸出用於分割文件路徑的字符串 win下為;,Linux下為:。 os.name:輸出字符串指示當前使用平台。win->'nt'; Linux->'posix'。 os.system("bash command"):運行shell命令,直接顯示。 os.environ:獲取系統環境變量。 os.path.abspath(path):返回path規范化的絕對路徑。 os.path.split(path):以元組的形式將path分割成的目錄和文件名返回。 os.path.dirname(path):返回path的目錄。其實就是os.path.split(path)的第一個元素。 os.path.basename(path):返回path最后的文件名。如果path以/或\結尾,那么就會返回空值。即os.path.split(path)的第二個元素。 os.path.exists(path):如果path存在,返回True;如果path不存在,返回False。 os.path.isabs(path):如果path是絕對路徑,返回True。 os.path.isfile(path):如果path是一個存在的文件,返回True。否則返回False。 os.path.isdir(path):如果path是一個存在的目錄,則返回True。否則返回False。 os.path.join(path1[, path2[, ...]]):將多個路徑組合后返回,第一個絕對路徑之前的參數將被忽略。 os.path.getatime(path):返回path所指向的文件或者目錄的最后存取時間。 os.path.getmtime(path):返回path所指向的文件或者目錄的最后修改時間。 os模塊中提供可以操作系統命令的方法,如os.system()、os.exec()、os.execvp()。 >>> p = '/Users/mac' >>> command = 'ls ' + p # 將命令以字符串的形式連接 >>> command 'ls /Users/mac' >>> os.system(command) # 執行系統命令 Desktop Movies PycharmProjects Documents Music Virtual Machines.localized Downloads Pictures __pycache__ Library Public test.py
os模塊中不論rmdir還是removedirs都不能直接刪除非空目錄。要直接刪除非空目錄,可以使用模塊shutil的rmtree()方法。
堆模塊
堆是計算機科學中一類特殊的數據結構的統稱,通常是一個可以被看作一棵樹的數組對象。
在計算機科學中,二叉樹是每個節點最多有兩個子樹的樹結構。通常子樹被稱為左子樹和右子樹。並不是所有的節點都有兩個子節點,稱每個節點都有兩個子節點的二叉樹為完全二叉樹。
堆模塊中的二叉樹結構特點:
節點的值大於等於(或小於等於)任何子節點的值。
節點左子樹和右子樹是一個二叉堆,如果父節點的值總是大於等於任何子節點的值,則為最大堆;否則為最小堆。
heapq模塊:
>>> import heapq >>> heapq.__all__ ['heappush', 'heappop', 'heapify', 'heapreplace', 'merge', 'nlargest', 'nsmallest', 'heappushpop'] heapq.heappush(heap, x): Help on built-in function heappush in module _heapq: heappush(...) heappush(heap, item) -> None. Push item onto heap, maintaining the heap invariant. heappush()函數自動按照二叉樹的結構將數據放到堆里面進行存儲。 >>> import heapq >>> heap = [] >>> heapq.heappush(heap, 2) >>> heapq.heappush(heap, 3) >>> heapq.heappush(heap, 9) >>> heapq.heappush(heap, 6) >>> heapq.heappush(heap, 5) >>> heapq.heappush(heap, 0) >>> heap [0, 3, 2, 6, 5, 9] # 最小堆 heapq.heappop(heap): Help on built-in function heappop in module _heapq: heappop(...) Pop the smallest item off the heap, maintaining the heap invariant. 這個函數是從heap堆中刪除一個最小的元素,並返回該值。刪除元素后,將會按照完全二叉樹的規范重新排列原堆。 >>> heapq.heappop(heap) # 刪除堆中最小的值 0 >>> heap # 按照完全二叉樹的規范重新排列原堆 [2, 3, 9, 6, 5] heapq.heapify(lst): Help on built-in function heapify in module _heapq: heapify(...) Transform list into a heap, in-place, in O(len(heap)) time. 將一個列表轉化為堆。 >>> lst = [2, 3, 5, 6, 8, 0, 9, 1] >>> heapq.heapify(lst) # 將列表ls轉化為堆 >>> lst # 堆 [0, 1, 2, 3, 8, 5, 9, 6] heapq.heapreplace(heap, x): Help on built-in function heapreplace in module _heapq: heapreplace(...) heapreplace(heap, item) -> value. Pop and return the current smallest value, and add the new item. This is more efficient than heappop() followed by heappush(), and can be more appropriate when using a fixed-size heap. Note that the value returned may be larger than item! That constrains reasonable uses of this routine unless written as part of a conditional replacement: if item > heap[0]: item = heapreplace(heap, item) 這是heappop()和heappush()的聯合,也就是刪除一個,同時加入一個,即替代。 >>> heap [2, 3, 9, 6, 5] >>> heapq.heapreplace(heap, 3.3) # 替代 2 >>> heap # 按照完全二叉樹規則重新排列 [3, 3.3, 9, 6, 5]
deque模塊
對於一個列表,可以用append方法向其末尾增加值,如果要向其首位增加值呢?可以使用collections下的deque模塊。
>>> from collections import deque >>> lst = [2, 5, 7, 9] >>> dlst = deque(lst) # 必須先將列表轉化為deque對象 >>> dlst # deque對象 deque([2, 5, 7, 9]) >>> dlst.append(12) # 添加到末尾 >>> dlst deque([2, 5, 7, 9, 12]) >>> dlst.appendleft(15) # 添加到首位 >>> dlst deque([15, 2, 5, 7, 9, 12]) >>> dlst.pop() # 刪除末尾值 12 >>> dlst deque([15, 2, 5, 7, 9]) >>> dlst.popleft() # 刪除首位值 15 >>> dlst deque([2, 5, 7, 9])
deque.rotate()方法實現列表的輪轉。rotate()中傳入整數,若為正整數,則順時針旋轉;若為負整數,則逆時針旋轉。旋轉方式是將原列表的deque對象首位連接成一個圓,列表的第一個值就是當前值。
>>> dlst deque([2, 5, 7, 9]) >>> dlst.rotate(3) # 順時針旋轉3個位置 >>> dlst deque([5, 7, 9, 2]) >>> dlst.rotate(-1) # 逆時針旋轉一個位置 >>> dlst deque([7, 9, 2, 5])
calendar模塊
month(year, month, w=2, l=1):
返回year年month月的日歷,兩行標題,一周一行。每日寬度間隔為w字符,每行的長度為7*w+6,l是每星期的行數。
>>> import calendar >>> cal = calendar.month(2018, 10) >>> print(cal) October 2018 Mo Tu We Th Fr Sa Su 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
calendar(year, w=2, l=1, c=6):
返回year年的年歷,3個月一行,間隔距離為c。每日寬度間隔為w個字符,每行長度為21*w+18+2*c,l是每星期行數。
isleap(year):
判斷是否為閏年,是則返回True,否則返回False。
>>> calendar.isleap(2018) False >>> calendar.isleap(2012) True
leapdays(y1, y2):
返回y1、y2兩年之間的閏年總數,包括y1,但不包括y2。
>>> calendar.leapdays(2000, 2020)
5
monthcalendar(year, month):
返回一個列表,列表內的元素還是列表。每個子列表代表一個星期,都是從星期一到星期日七個元素,如果沒有本周的日期,則為0。
>>> calendar.monthcalendar(2018, 10) [[1, 2, 3, 4, 5, 6, 7], [8, 9, 10, 11, 12, 13, 14], [15, 16, 17, 18, 19, 20, 21], [22, 23, 24, 25, 26, 27, 28], [29, 30, 31, 0, 0, 0, 0]] # 用0填充
monthrange(year, month):
返回一個元組,里面有兩個整數。第一個整數代表着該月的第一天從星期幾開始(從0開始依次為星期一、星期二……直到6代表星期日)。第二個整數代表該月一共有多少天。
>>> calendar.monthrange(2018, 10) (0, 31) # 2018年10從星期一開始,共有31天 >>> calendar.monthrange(2018, 11) (3, 30) # 2018年11從星期四開始,共有30天
weekday(year, month, day):
輸入年月日,返回該日是星期幾(返回值從0開始依次為星期一、星期二……直到6代表星期日)。
>>> calendar.weekday(2018, 10, 23) 1 # 星期二 >>> calendar.weekday(2018, 10, 31) 2 # 星期三
time模塊
time():
獲得當前的時間戳,它是以1970年1月1日0時0分0秒為計時起點到當前的秒數。
>>> time.time()
1540883899.987189
localtime():
返回一個本地時間元組。
>>> time.localtime()
time.struct_time(tm_year=2018, tm_mon=10, tm_mday=30, tm_hour=15, tm_min=21, tm_sec=24, tm_wday=1, tm_yday=303, tm_isdst=0)
元組中各項含義如下表所示。
索引 |
屬性 |
含義 |
0 |
tm_year |
年 |
1 |
tm_mon |
月 |
2 |
tm_mday |
日 |
3 |
tm_hour |
時 |
4 |
tm_min |
分 |
5 |
tm_sec |
秒 |
6 |
tm_wday |
一周中的第幾天 |
7 |
tm_yday |
一年中的第幾天 |
8 |
tm_isdst |
夏令時 |
time.localtime()是可以有參數的,只是它默認以time.time()的時間戳為參數。我們可以給它傳入一個時間戳作為參數,它將返回該時間戳對應的時間元組。
>>> time.localtime(1200060000) # 傳入一個時間戳 time.struct_time(tm_year=2008, tm_mon=1, tm_mday=11, tm_hour=22, tm_min=0, tm_sec=0, tm_wday=4, tm_yday=11, tm_isdst=0)
gmtime():
localtime()得到的是本地時間,而gmtime()得到的是國際化的格林尼治時間,它的結構和本地時間一致。
>>> time.gmtime()
time.struct_time(tm_year=2018, tm_mon=10, tm_mday=30, tm_hour=7, tm_min=37, tm_sec=18, tm_wday=1, tm_yday=303, tm_isdst=0)
asctime():
>>> time.asctime() 'Tue Oct 30 15:41:01 2018'
time.asctime()的參數為空時,默認使用本地時間time.localtime()的時間元組格式為參數,返回當前的星期、月、日、時間、年,顯示相對友好。也可自己傳入參數,但傳入的參數必須是時間元組的格式。
>>> time.asctime(time.localtime(1200060000)) 'Fri Jan 11 22:00:00 2008'
ctime():
>>> time.ctime() 'Tue Oct 30 15:46:24 2018'
ctime()的用法、返回值和asctime()一致,不同在於asctime()是以時間元組為參數,而ctime()是以時間戳為參數。ctime()默認傳入time.time()定義的時間戳,也可自己傳入時間戳參數。
>>> time.ctime(1200060000) 'Fri Jan 11 22:00:00 2008'
mktime():
mktime()可以看作是localtime()的逆過程,是將時間元組格式轉換為時間戳的格式。
>>> time.mktime(time.localtime())
1540886368.0
strftime():
Help on built-in function strftime in module time:
strftime(...)
strftime(format[, tuple]) -> string
Convert a time tuple to a string according to a format specification.
See the library reference manual for formatting codes. When the time tuple is not present, current time as returned by localtime() is used.
將時間元組按照指定的格式轉換為字符串,如果不指定時間元組,就默認為當前的localtime()值。
>>> time.strftime('%Y-%m-%d') # 分隔符可以自由指定 '2018-10-30' >>> time.strftime('%Y/%m/%d') '2018/10/30' >>> time.strftime('%Y/%m/%d', time.localtime(1200060000)) '2008/01/11'
時間字符串格式
格式 |
含義 |
取值范圍(格式) |
%y |
去掉世紀的年份 |
00~99,如18 |
%Y |
完整的年份 |
如2018 |
%j |
指定日期是一年中的第幾天 |
001~366 |
%m |
返回月份 |
01~12 |
%b |
本地簡化月份的名稱 |
簡寫英文月份 |
%B |
本地完整月份的名稱 |
完整英文月份 |
%d |
該月的第幾日 |
如5月1日返回01 |
%H |
該日的第幾時(24小時制) |
00~23 |
%l |
該日的第幾時(12小時制) |
01~12 |
%M |
分鍾 |
00~59 |
%S |
秒 |
00~59 |
%U |
該年中的第幾個星期(以周日為一周起點) |
00~53 |
%W |
同上,以周一為一周的起點 |
00~53 |
%w |
一星期中的第幾天 |
0~6 |
%Z |
時區 |
在中國大陸測試返回CST,即China Standard Time |
%x |
日期 |
日/月/年 |
%X |
時間 |
時:分:秒 |
%c |
詳細日期時間 |
日/月/年時:分:秒 |
%% |
%字符 |
%字符 |
%p |
上下午 |
AM或PM |
strptime():
是strftime()的逆過程,將字符串格式化時間轉換為時間元組的形式。
Help on built-in function strptime in module time:
strptime(...)
strptime(string, format) -> struct_time
Parse a string to a time tuple according to a format specification.
See the library reference manual for formatting codes (same as strftime()).
strptime()要傳入兩個參數,第一個參數是字符串格式化時間,第二個參數是與傳入的字符串格式化時間相對應的格式,即傳入的字符串格式化時間的格式是什么,第二個參數傳入的格式就要完全與其對應。
>>> today = time.strftime('%Y-%m-%d %H:%M:%S') >>> today '2018-10-30 16:56:13' >>> time.strptime(today, '%Y-%m-%d %H:%M:%S') time.struct_time(tm_year=2018, tm_mon=10, tm_mday=30, tm_hour=16, tm_min=56, tm_sec=13, tm_wday=1, tm_yday=303, tm_isdst=-1)
datetime模塊
datetime模塊中有以下幾個類。
date:日期類,常用的屬性有year/month/day。
time:時間類,常用的有hour/minute/second/microsecond。
datetime:日期時間類。
timedelta:時間間隔,即兩個時間點之間的時間長度。
tzinfo:時區類。
date類
>>> [item for item in dir(datetime.date) if not item.startswith('_')] ['ctime', 'day', 'fromisoformat', 'fromordinal', 'fromtimestamp', 'isocalendar', 'isoformat', 'isoweekday', 'max', 'min', 'month', 'replace', 'resolution', 'strftime', 'timetuple', 'today', 'toordinal', 'weekday', 'year']
可以看到date類中有很多的方法和屬性,就幾個常用的作簡單介紹。
>>> td = datetime.date.today() # 生成一個日期對象 >>> td # 可以利用這個日期對象操作各種屬性和方法 datetime.date(2018, 10, 30) >>> print(td) # 以字符串的形式打印日期 2018-10-30 >>> print(td.ctime()) # 調用對象的ctime()方法,將日期轉換為星期、月、日、時間、年 Tue Oct 30 00:00:00 2018 >>> print(td.timetuple()) # 調用對象的timetuple()方法,將日期轉換為時間元組 time.struct_time(tm_year=2018, tm_mon=10, tm_mday=30, tm_hour=0, tm_min=0, tm_sec=0, tm_wday=1, tm_yday=303, tm_isdst=-1) >>> print(td.toordinal()) # 調用對象的toordinal()方法,將日期轉換為ordinal時間 736997 >>> print(td.year) # 調用對象的year屬性,取出日期對象的年 2018 >>> print(td.month) # 調用對象的month屬性,取出日期對象的月 10 >>> print(td.day) # 調用對象的day屬性,取出日期對象的日 30 >>> print(datetime.date.fromordinal(736997)) # 調用對象的fromordinal()方法, 2018-10-30 # 將ordinal時間轉換為字符格式的時間 >>> print(datetime.date.fromtimestamp(time.time())) # 調用date類的 2018-10-30 # fromtimestamp()方法將時間戳轉換為字符格式的時間 >>> d1 = datetime.date(2018, 10, 29) # 實例化date類對象 >>> d1 datetime.date(2018, 10, 29) >>> print(d1) 2018-10-29 >>> d2 = d1.replace(year=2008, day=9) # 調用對象的replace()方法,修改日期 >>> print(d2) # 並返回一個新的已修改的日期對象 2008-10-09
time類
>>> [item for item in dir(datetime.time) if not item.startswith('_')] ['dst', 'fold', 'fromisoformat', 'hour', 'isoformat', 'max', 'microsecond', 'min', 'minute', 'replace', 'resolution', 'second', 'strftime', 'tzinfo', 'tzname', 'utcoffset'] 可以看到time類中有很多的方法和屬性,就幾個常用的作簡單介紹。 >>> tm = datetime.time(1, 2, 3) # 生成time類對象 >>> tm datetime.time(1, 2, 3) >>> print(tm) 01:02:03 >>> print(tm.hour) # 調用對象的hour屬性,取出時間對象的時 1 >>> print(tm.minute) # 調用對象的minute屬性,取出時間對象的分 2 >>> print(tm.second) # 調用對象的second屬性,取出時間對象的秒 3 >>> print(tm.tzinfo) # 調用對象的tzinfo屬性,取出時間對象的時區信息 None
timedelta類
timedelta類主要是用來做時間的運算。
>>> now = datetime.datetime.now() # 獲取當前時間 >>> print(now) 2018-10-30 20:59:34.799856 >>> b = now + datetime.timedelta(hours=5) # 對now增加5小時 >>> print(b) 2018-10-31 01:59:34.799856 >>> c = now + datetime.timedelta(weeks=2) # 對now增加兩周 >>> print(c) 2018-11-13 20:59:34.799856 >>> d = c - b # 計算時間差 >>> print(d) 13 days, 19:00:00
random模塊
random.random():0-1之間的隨機浮點數,不包含0和1。
random.randint(a, b):a和b之間的任意整數,包含a和b。
random.randrange(a, b):a和b之間的任意整數,包含a,不包含b。
random.uniform(a, b):a和b之間的任意浮點數。
random.shuffle(item):將可迭代對象item中的順序打亂,原地修改,沒有返回值。
xml.etree.ElementTree模塊(處理XML)
XML的定義:
XML指可擴展標記語言(EXtensible Markup Language);
XML是一種標記語言,類似HTML;
XML的設計宗旨是傳輸數據,而非顯示數據;
XML標簽沒有被預定義,而需自行定義標簽;
XML被設計為具有自我描述特性。
python提供了多種模塊來處理XML,下面介紹xml.etree.ElementTree(簡稱ET):元素樹。
先做一個XML文檔,基於此文檔練習。
這是一棵樹,寫成XML文檔格式:
<bookstore> <book category="COOKING"> <title lang="en">Everyday Italian</title> <author>Giada De Laurentiis</author> <year>2005</year> <price>30.00</price> </book> <book category="CHILDREN"> <title lang="en">Harry Potter</title> <author>J K. Rowling</author> <year>2005</year> <price>29.99</price> </book> <book category="WEB"> <title lang="en">Learning XML</title> <author>Erik T. Ray</author> <year>2003</year> <price>39.95</price> </book> </bookstore>
以上的XML文檔,保存並命名為web.xml文件。利用python中的模塊進行處理。
>>> import xml.etree.ElementTree as ET >>> tree = ET.ElementTree(file='web.xml') # 建立XML解析樹對象 >>> tree <xml.etree.ElementTree.ElementTree object at 0x10b545828>
建立起XML解析樹對象,然后通過根節點向下開始讀取各個元素對象。
在上述的XML文檔中,根元素是bookstore,它沒有屬性,或者屬性為空。 >>> root = tree.getroot() # 通過對象獲取根節點 >>> root.tag # 根節點的標簽名 'bookstore' >>> root.attrib # 根節點的屬性 {} 通過如下的操作,將根節點下面的元素都讀出來。 >>> for child in root: # 獲取根節點下面的一級子節點 ... print(child.tag, child.attrib) ... book {'category': 'COOKING'} book {'category': 'CHILDREN'} book {'category': 'WEB'} 也可以這樣讀取指定元素的信息: >>> root[0].tag # 獲取根節點下一級子節點的信息 'book' >>> root[0].attrib {'category': 'COOKING'} >>> root[0].text # 沒有內容 '\n ' 再深入一層,獲取子孫節點的信息: >>> root[0][0].tag # 子孫節點的信息 'title' >>> root[0][0].attrib {'lang': 'en'} >>> root[0][0].text 'Everyday Italian' 對於ElementTree對象,有一個iter()方法可以對指定名稱的子節點進行深度優先遍歷。 >>> for ele in tree.iter(tag='book'): # 遍歷名稱為book的節點 ... print(ele.tag, ele.attrib) ... book {'category': 'COOKING'} book {'category': 'CHILDREN'} book {'category': 'WEB'} >>> for ele in tree.iter(tag='title'): # 遍歷名稱為title的節點 ... print(ele.tag, ele.attrib, ele.text) ... title {'lang': 'en'} Everyday Italian title {'lang': 'en'} Harry Potter title {'lang': 'en'} Learning XML 如果不指定元素名稱,就是將所有的元素遍歷一遍。 >>> for ele in tree.iter(): # 不指定元素名稱,遍歷所有元素 ... print(ele.tag, ele.attrib) ... bookstore {} book {'category': 'COOKING'} title {'lang': 'en'} author {} year {} price {} book {'category': 'CHILDREN'} title {'lang': 'en'} author {} year {} price {} book {'category': 'WEB'} title {'lang': 'en'} author {} year {} price {} 通過路徑搜索到指定的元素,讀取其內容,類似於xpath。 >>> for ele in tree.iterfind('book/title'): # 通過路徑搜索到指定的元素 ... print(ele.text) ... Everyday Italian Harry Potter Learning XML 利用findall()方法,也可以實現查找功能。 >>> for ele in tree.findall('book'): ... title = ele.find('title').text ... price = ele.find('price').text ... lang = ele.find('title').attrib ... print(title, price, lang) ... Everyday Italian 30.00 {'lang': 'en'} Harry Potter 29.99 {'lang': 'en'} Learning XML 39.95 {'lang': 'en'} 除了讀取有關數據,還能對XML進行編輯,即增、刪、改、查功能。 >>> root[1].tag 'book' >>> del root[1] # 刪除一個節點 >>> for ele in root: ... print(ele.tag) ... book book
成功刪除了一個節點,原來有三個book節點,現在就剩下兩個了。但是源文件里卻並沒有刪除節點,這是因為至此的修改還是停留在內存中,還沒有將修改的結果輸出到文件。我們是在內存中創建的ElementTree對象,對此對象進行操作的。
可以這樣做,將修改后的內容保存到文件中。 >>> import os >>> outpath = os.getcwd() >>> file = outpath + 'web.xml' # 拼接當前文件路徑 >>> tree.write(file) # 修改后的內容寫入文件保存 上面是用del來刪除某個元素,在編程中,更多的會用remove()方法來執行刪除操作。 >>> for book in root.findall('book'): ... price = book.find('price').text ... if float(price) > 40: # 刪除價格大於40的標簽 ... root.remove(book) ... >>> for price in root.iter('price'): ... print(price.text) # 價格大於40的標簽被刪除 ... 37.0 除了刪除,還可以修改內容。 >>> for price in root.iter('price'): # 原來的內容 ... print(price.text) ... 30.00 39.95 >>> for price in root.iter('price'): # 修改后的內容,價格上漲7元 ... new_price = float(price.text) + 7 ... price.text = str(new_price) ... price.set('updated', 'up') # 設置屬性 ... >>> for price in root.iter('price'): ... print(price.text) ... 37.0 46.95 增加元素。 >>> for ele in root: ... print(ele.tag) ... book # 原文件里只有一個book標簽 >>> ET.SubElement(root, 'book') # 在root里面添加book節點 <Element 'book' at 0x1022f5f98> >>> for ele in root: ... print(ele.tag) ... book book # 新增的book節點 >>> b = root[1] # 得到新增的book節點 >>> b.text = 'python' # 添加內容 >>> for ele in root: ... print(ele.tag, ele.text) ... book book python # 添加的內容 自己創建XML文檔 import xml.etree.ElementTree as ET new_xml = ET.Element("namelist") name = ET.SubElement(new_xml,"name",attrib={"enrolled":"yes"}) age = ET.SubElement(name,"age",attrib={"checked":"no"}) sex = ET.SubElement(name,"sex") sex.text = '33' name2 = ET.SubElement(new_xml,"name",attrib={"enrolled":"no"}) age = ET.SubElement(name2,"age") age.text = '19' et = ET.ElementTree(new_xml) #生成文檔對象 et.write("test.xml", encoding="utf-8",xml_declaration=True) ET.dump(new_xml) #打印生成的格式 創建xml文檔
ET里常用的屬性和方法總結:
Element對象
常用屬性如下。 tag:string,元素數據種類。 text:string,元素的內容。 attrib:dictionary,元素的屬性字典。 tail:string,元素的尾形。 針對屬性的操作如下。 clear():清空元素的后代、屬性、text和tail也設置為None。 get(key, default=None):獲取key對應的屬性值,如果該屬性不存在,則返回default值。 items():根據屬性字典返回一個列表,列表元素為(key, value)。 keys():返回包含所有元素屬性鍵的列表。 set(key, value):設置新的屬性鍵與值。 針對后代的操作如下。 append(subelement):添加直系子元素。 extend(subelements):增加一串元素對象作為子元素。 find(match):尋找第一個匹配子元素,匹配對象可以為tag或path。 findall(match):尋找所有匹配子元素,匹配對象可以為tag或path。 findtext(match):尋找第一個匹配子元素,返回其text值,匹配對象可以為tag或path。 insert(index, element):在指定位置插入子元素。 iter(tag=None):生成遍歷當前元素所有后代或者給定tag的后代的迭代器。 iterfind(match):根據tag或path查找所有的后代。 itertext():遍歷所有后代並返回text值。 remove(subelement):刪除子元素。
ElementTree對象
find(match)。 findall(match)。 findtext(match, default=None)。 getroot():獲取根節點。 iter(tag=None)。 iterfind(match)。 parse(source, parser=None):裝載XML對象,source可以為文件名或文件類型對象。 write(file, encoding=’us-ascii’, xml_declaration=None, default_namespace=None, method=’xml’)。
JSON模塊
如果我們要在不同的編程語言之間傳遞對象,就必須把對象序列化為標准格式,比如XML。但更好的方法是序列化為JSON,因為JSON表示出來就是一個字符串,可以被所有語言讀取,也可以方便地存儲到磁盤或者通過網絡傳輸。JSON不僅是標准格式,並且比XML更快,而且可以直接在Web頁面中讀取,非常方便。
JSON表示的對象就是標准的JavaScript語言的對象,JSON和Python內置的數據類型對應如下:
就傳遞數據而言,XML是一種選擇,JSON也是一種選擇。JSON是一種輕量級的數據交換格式,可以在任何語言之間進行數據的傳遞。
JSON建構於兩種結構:
“名稱/值”對的集合(A collection of name/value pairs)。不同的語言中,它被理解為對象(object),紀錄(record),結構(struct),字典(dictionary),哈希表(hash table),有鍵列表(keyed list),或者關聯數組 (associative array)。
值的有序列表(An ordered list of values)。在大部分語言中,它被理解為數組(array)。
python標准庫中有JSON模塊,主要執行序列化和反序列化功能,實現不同語言的數據類型和json數據類型之間的轉換。
序列化:
我們把對象(變量)從內存中變成可存儲或傳輸的過程稱之為序列化,在Python中叫pickling,在其他語言中也被稱之為serialization,marshalling,flattening等等,都是一個意思。
序列化之后,就可以把序列化后的內容寫入磁盤,或者通過網絡傳輸到別的機器上。反過來,把變量內容從序列化的對象重新讀到內存里稱之為反序列化,即unpickling。
序列化:encoding,把一個python對象編碼轉換為JSON字符串;
反序列化:decoding,把JSON格式字符串解碼轉換為python數據對象。
基本操作:
>>> import json >>> json.__all__ ['dump', 'dumps', 'load', 'loads', 'JSONDecoder', 'JSONDecodeError', 'JSONEncoder'] 1. encoding:dumps() >>> data = [{'name': 'xx', 'lang': ('python', 'java'), 'age': 22}] >>> data [{'name': 'xx', 'lang': ('python', 'java'), 'age': 22}] >>> data_json = json.dumps(data) >>> data_json '[{"name": "xx", "lang": ["python", "java"], "age": 22}]'
encoding的操作比較簡單,注意觀察data和data_json的區別,lang的值從元組變成了列表;data中的元素不論是以雙引號還是單引號,json的dumps都會處理為雙引號。即json會先將原數據中的單引號變成雙引號,然后將整個數據包裝成符合json格式的字符串。二者的類型也有區別。
>>> type(data) <class 'list'> >>> type(data_json) # json的dumps將傳入的數據轉換為了符合json格式的字符串類型 <class 'str'> 2. decoding:loads() >>> new_data = json.loads(data_json) >>> new_data [{'name': 'xx', 'lang': ['python', 'java'], 'age': 22}] # lang的值依然是列表,沒有轉回元組 >>> type(new_data) <class 'list'> JSON的dumps()提供了可選參數,能夠在輸出上更友好。 >>> data_j = json.dumps(data, sort_keys=True, indent=2) >>> print(data_j) [ { "age": 22, "lang": [ "python", "java" ], "name": "xx" } ]
sort_keys=True, 意思是按照鍵的字典順序排序;indent=2是讓每個鍵值對顯示的時候,以縮進兩個字符對齊。
pickle模塊
pickle模塊的使用方法和用途和json完全一致,pickle中的函數名稱和用法和json也完全一致。區別在於pickle支持更多的數據類型:支持類,而json不支持類。除此之外,pickle的dumps將數據轉換為bytes類型,而json的dumps將數據轉換為json字符串類型。pickle只適用於python,而json適用於所有語言。
# 序列化 import pickle dic={'name':'alvin','age':23,'sex':'male'} print(type(dic)) <class 'dict'> j=pickle.dumps(dic) print(type(j)) <class 'bytes'> f=open('序列化對象_pickle','wb') # 注意是w是寫入str,wb是寫入bytes,j是'bytes' f.write(j) # 等價於pickle.dump(dic,f) f.close() # 反序列化 import pickle f=open('序列化對象_pickle','rb') data=pickle.loads(f.read()) # 等價於data=pickle.load(f) print(data['age'])
Pickle的問題和所有其他編程語言特有的序列化問題一樣,它只能用於Python,並且可能不同版本的Python彼此都不兼容,因此,只能用Pickle保存那些不重要的數據,不能成功地反序列化也沒關系。