1. 程式人生 > >python標準模組

python標準模組

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'