SlideShare una empresa de Scribd logo
1 de 119
Descargar para leer sin conexión
11. 常用內建模組
• 學習目標
– 處理日期與時間
– 認識日誌的使用
– 運用規則表示式
– 管理檔案與目錄
– URL 處理
2
時間的度量
• 格林威治標準時間
– 經常簡稱 GMT 時間
– 常不嚴謹(且有爭議性)地當成是 UTC 時間
• 世界時
– 藉由觀測遠方星體跨過子午線而得
– 在 1972 年導入 UTC 之前,GMT 與 UT 是相
同的
3
• 國際原子時
– 將秒的國際單位(International System of
Units, SI)定義為銫(caesium)原子輻射振
動 9192631770 周耗費的時間
– 時間從 UT 的 1958 年開始同步
• 世界協調時間
– 折衷修正版本的世界協調時間,常簡稱為 UTC
– 1972 年 UTC採用了閏秒(leap second)修正
4
• Unix 時間
– UTC 時間 1970 年(Unix 元年)1 月1 日
00:00:00 為起點而經過的秒數
– 不考慮閏秒修正,用以表達時間軸上某一瞬間
• epoch
– 某個特定時間的起點,時間軸上某一瞬間
– Unix epoch 選為UTC 時間 1970 年 1 月 1 日
00:00:00
5
• 就目前來說,即使標註為 GMT,實際上談
到時間指的是UTC 時間
• 秒的單位定義是基於 TAI,也就是銫原子輻
射振動次數
• UTC 考量了地球自轉越來越慢而有閏秒修
正
• Unix 時間是 1970 年 1 月 1 日 00:00:00 為
起點而經過的秒數,不考慮閏秒
6
年曆與時區簡介
• 儒略曆
– 修正了羅馬曆隔三年設置一閏年的錯誤,改採
四年一閏
• 格里高利曆
– 改革了儒略曆
– 將儒略曆 1582 年 10 月 4 日星期四的隔天,
訂為格里高利曆 1582 年 10 月 15 日星期五
– 各個國家改曆的時間並不相同
7
8
• ISO8601 標準
– 嚴格來說並非年曆系統,而是時間日期表示方
法的標準,用以統一時間日期的資料交換格式
– 19 世紀是指 1900 至 1999 年(包含該年),
而格里高利曆的 19 世紀是指 1801 年至 1900
年(包含該年)
9
時區
• 各種時間日期的議題中最複雜的
• 牽涉到地理、法律、經濟、社會甚至政治
等問題
• UTC 偏移(offset)
– 大致上來說,經度每 15 度是偏移一小時
– 通常會在時間的最後標識 Z 符號
– 有些國家的領土橫跨的經度很大,一個國家有
多個時間反而造成困擾,因而不採取每 15 度
偏移一小時的作法
10
• 日光節約時間
– 也稱為夏季時間(Summer time)
– 有些高緯度國家,夏季、冬季日照時間差異很
大,為了節省能源會儘量利用夏季日照
– 台灣也曾實施過日光節約時間,後來因為沒太
大實質作用而取消
11
• 如果想獲取系統的時間,Python 的 time
模組提供了一層介面,用來呼叫各平台上
的C 程式庫函式,它提供的相關函式,通常
與 epoch 有關
12
• gmtime() 傳回了 struct_time 實例
13
• time.gmtime(0) 表示從 epoch 起算經
過了 0 秒
• 如果不指定數字,表示取得目前的時間並
傳回 struct_time 實例
14
• UTC 是一種絕對時間,與時區無關,也沒
有日光節約時間的問題
• time.time() 傳回的是浮點數
• time 模組提供的是低階的機器時間觀點,
也就是從 epoch 起經過的秒數
• 有些輔助函式,可以作些簡單的轉換,以
便成為人類可理解的時間概念
15
• localtime()則可提供目前所在時間
16
• 有個代表時間的字串,想要將其剖析為
struct_time 實例,可以使用
strptime() 函式
17
• 如果你有個 struct_time 物件,想要轉
換為從 epoch 起經過之秒數,可以使用
mktime()
18
• ctime(secs) 是
asctime(localtime(secs))的封裝
• asctime() 可指定 struct_time 實例,
取得一個簡單的時間字串描述
19
• strftime() 接受一個格式指定與
struct_time 實例
20
• time 模組提供的終究是低階的機器時間觀
點,用來表示人類可理解的時間概念並不
方便
• 若想從人類的觀點來表示時間,可以進一
步使用 datetime 模組
21
使用 datetime 模組
• 人類在時間的表達上有時只需要日期、有
時只需要時間,有時會同時表達日期與時
間
• 通常不會特別聲明時區
• 可能只會提及年、月、年月、月日、時分
秒等
22
• 對於人類時間表達,datetime 模組提供
–datetime(包括日期與時間)
–date(只有日期)
–time(只有時間)
23
• 若想使用 UTC 時間來建立 datetime 實例
24
• 有個 datetime 或 date 實例,想將它們包含
的時間概念轉換為 UTC 時間戳記
• 有個時間戳記,也可以透過 datetime 或
date 的 fromtimestamp() 來建立
datetime 或 date 實例
25
• datetime、date、time 實例都有個
isoformat() 方法,可傳回時間字串描述
• 採用的是 ISO8601 標準,當日期與時間同
時表示時,預設會使用 T 來分隔,若必要
也可以自行指定
26
• datetime 類別的 strptime() 類別方法,
會傳回 datetime 實例
27
• 如果需要進行日期或時間的運算,可以使
用 datetime 的 timedelta 類別方法
• 想知道加上 3 週又 5 天 8 小時35 分鐘後的
日期時間是什麼?
• 2014 年 2 月 21 日加 9 天會是幾月幾號?
28
• datetime 實例本身預設並沒有時區資訊,
此時單純表示本地時間
• datetime 類別上的 tzinfo 類別,可以繼
承以實作時區的相關資訊與操作
• 從 Python 3.2 開始,datetime 類別新增
了timezone 類別,它是 tzinfo 的子類
別,用來提供基本的 UTC 偏移時區實作
29
• 想將 utc 轉換為台灣的時區
• 內建的 timezone 只單純考量了UTC 偏移,
不考量日光節約時間等其他因素
30
• 若需要 timezone 以外的其他時區定義,
可以額外安裝社群貢獻的 pytz 模組
• 可以使用 pip install pytz 來安裝
31
• pytz 的 timezone 也可以解決棘手的日
光節約時間問題
32
• 在台灣時區, 1975 年 3 月 31 日 23 時 40
分 0 秒加一個小時的時間會是多少呢?
• 使用了 normalize() 之後,才能得到考
量了日光節約時間的正確時間
33
• 一個常見的建議是,使用 UTC 來進行時間
的儲存或操作
• 因為UTC 是絕對時間,不考量日光節約時
間等問題
• 在必須使用當地時區的場合時,再使用
datetime 實例的 astimezone() 做轉換
34
日誌
• 一般來說,一個模組只需要一個 Logger
實例
• 建議透過 logging.getLogging() 來取
得 Logger 實例
• 呼叫 getLogger() 時,可以指定名稱,
相同名稱下取得的 Logger 會是同一實例
35
• 呼叫 getLogger() 時可以不指定名稱,
這時會取得根 Logger
• 父階層相同的 Logger,父 Logger 的組
態相同
• 想要套件中的模組在進行日誌時,都使用
相同的父組態,可以在套件的 __init__.py
檔案中撰寫:
36
37
• Logger 有階層關係
• 每個 Logger 處理完自己的日誌動作後,
會再委託父 Logger 處理
• 在不調整父 Logger 組態的情況下,直接
設定 Logger 實例,就只能設定為更嚴格
的日誌層級,才會有實際的效用
38
39
• 如果想要調整根 Logger 的組態,可以使
用 logging.basicConfig()
40
• 根 Logger 的日誌訊息預設會輸出至
sys.stderr
• 想要修改能輸出至檔案,可以使用
logging.basicConfig() 指定
filename 參數
• 子 Logger 實例可以透過 addHandler()
新增自己的處理器
41
• 若要自訂格式,可以透過
logging.Formatter() 建立
Formatter 實例, 再透過處理器的
setFormatter() 設定
42
• 定義過濾器可以繼承 logging.Filter 類
別並定義 filter(record) 方法
• 或者是定義一個物件具有
filter(record) 方法
• 自 Python 3.2 之後,也可以使用函式作為
過濾器了
• Logger 或 Handler 實例都有
addFilter() 方法,可以新增過濾器
43
44
使用 logging.config
• 在 Python 的 logging 模組官方文件中有
個範例
45
46
• 自 Python 3.2 開始,建議改用
logging.config.dictConfig()
47
48
49
50
簡介規則表示式
• 想根據某個字元或字串切割,可以使用str
的 split()
• 如果切割字串的依據不單只是某個字元或
子字串,而是任意單一數字呢?
51
• 使用 re 模組來支援規則表示式
52
• 因為  在Python 字串中被作為轉義字元,
因此要撰寫規則表示式時,必須撰寫為
'd'
• 在撰寫規則表示式時,建議使用原始字串
53
• 規則表示式基本上包括兩種字元:
– 字面字元(Literals)
– 詮譯字元(Metacharacters)
• 字面字元是指按照字面意義比對的字元
• 詮譯字元是不按照字面比對,在不同情境
有不同意義的字元
• 找出並理解詮譯字元想要詮譯的概念,對
於規則表示式的閱讀非常重要
54
• 字母和數字在規則表示式中,都是按照字
面意義比對
• 有些字元之前加上了  之後,會被當作詮
譯字元
55
56
• 詮譯字元在規則表示式中有特殊意義,例
如! $ ^ * ( ) + = { } [ ] |
 : . ?等
• 若要比對這些字元,則必須加上忽略符號
• 如果不確定哪些標點符號字元要加上忽略
符號,可以在每個標點符號前加上 ,例
如比對逗號也可以寫 ,
57
• 如果規則表示式為 XY,那麼表示比對「X
之後要跟隨著 Y」
• 如果想表示「X 或 Y」,可以使用 X|Y
• 如果有多個字元要以「或」的方式表示,
例如「X 或 Y 或 Z」,則可以使用字元類表
示為[XYZ]
58
• 規則表示式中,多個字元可以歸類在一起,
成為一個字元類(Character class)
• 字元類會比對文字中是否有「任一個」字
元符合字元類中某個字元
• 規則表示式中被放在 [] 中的字元就成為一
個字元類
59
• | 在字元類別只是個普通字元,不會被當作
「或」來表示
• 字元類中可以使用連字號 - 作為字元類詮譯
字元,表示一段文字範圍
• 字元類中可以使用 ^ 作為字元類詮譯字元,
[^] 則為反字元類(Negated character
class)
60
61
• 就規則表示式本身的發展歷史來說,早期
並不支援Unicode
• 例如預定義字元類早期就未考量Unicode規
範,像是w預設只比對ASCII字元
• Python 3預設就支援Unicode模式,預定
義字元類在比對上不限於ASCII字元
62
• d在Python中,預設並不只比對ASCII數
字0至9
63
• 貪婪量詞會儘可能地找出長度最長的符合
文字
64
• 在貪婪量詞表示法後加上? , 將會成為逐
步量詞( Reluctant quantifier)
• 逐步量詞會儘可能地找出長度最短的符合
文字
65
• 有個文字Justin dog Monica doggie Irene,
你想要直接依當中單字 dog 切出前後兩個
子字串?
• 可以使用 b 標出單字邊界
66
67
• 可以使用 () 來將規則表示式分組,除了作
為子規則表示式之外,還可搭配量詞使用
• 例如想要驗證電子郵件格式,域名稱可以
有數層,必須是大小寫英文字元或數字
– ^[a-zA-Z]+d*@([a-zA-Z0-9]+.)+com
68
• 被分組的規則表示式,還可以在稍後回頭
參考(Back reference)
• 如果有個規則表示式 ((A)(B(C))),其中
有四個分組
69
• 分組回頭參考時,是在  後加上分組計數,
表示參考第幾個分組的比對結果
• dd 要求比對兩個數字,(dd)1 的話,
表示要輸入四個數字,輸入的前兩個數字
與後兩個數字必須相同
• ["'][^"']*["'] 比對單引號或雙引號中
0 或多個字元,但沒有比對兩個都要是單引
號或雙引號
• (["'])[^"']*1 則比對出前後引號必須
一致
70
• 規則表示式中的(?…)代表擴充標記
• 可以使用(?:…)來表示不捕捉分組
• 使用(?P<name>…)來為分組命名,在同一
個規則表示式中使用(?P=name)取用分組
71
• 如果想比對出的對象,之後必須跟隨或沒
有跟隨著特定文字,可以使用(?=…)或
(?!…)
• 如果想比對出的對象,前面必須有或沒有
著特定文字,可以使用(?<=…)或(?<!…)
72
• (?(id/name)yes-pattern|no-
pattern)根據先前是否有符合的分組,動
態地組成整個規則表示式
73
74
Pattern 與 Match 物件
• 剖析、驗證規則表示式往往是最耗時間的
階段
• 在頻繁使用某規則表示式的場合,若可以
將剖析、驗證過後的規則表示式重複使用,
對效率將會有所幫助
75
• re.compile() 可以建立規則表示式物件,
在剖析、驗證過規則表示式無誤後傳回的
規則表示式物件可以重複使用
• 可以指定 flags 參數,進一步設定規則表
示式物件的行為
76
• 也可以在規則表示式中使用嵌入旗標表示
法( Embedded Flag Expression)
• 例如 re.IGNORECASE 等效的嵌入旗標表
示法為 (?i),以下片段效果等同上例:
77
• 行內旗標可使用的字元有i、a、m、s、L、
x,各自對應:
– re.IGNORECASE或re.I:(?i)
– re.ASCII或re.A:(?a)
– re.MULTILINE或re.M:(?m)
– re.DOTALL或re.S:(?s)
– re.LOCALE或re.L:(?L)
– re.VERBOSE或re.X:(?x)
78
• 可以使用 finditer()方法,它會傳回一
個 iterable 物件,每一次迭代都會得到一
個 Match 物件
79
• search() 方法與 match() 方法必須小心
區分,search() 會在整個字串中,
• 找尋第一個符合的子字串,而 match() 只
會在字串開頭看看接下來的字串是否符合
80
• 如果規則表示式中設定了分組,findall()
方法會以清單傳回各個分組
• 如果想要取得 1212、4545、9999 這樣的
結果,要使用 finditer() 方法
81
• 若想找出單引號或雙引號中的文字,如下
使用 findall() 是行不通的:
82
• 如果要找出單引號或雙引號中的文字,必
須如下:
83
• 也可以使用 group() 指定數字,表示要取
得哪個分組,或者是使用 groups() 傳回
一個 tuple,其中包含符合的分組
84
• 如果要取代符合的子字串,可以使用規則
表示式物件的 sub()方法
85
• 如果規則表示中有分組設定,在使用 sub()
時,可以使用 num 來捕捉被分組匹配文字
• 如果使用了(?P<name>…)為分組命名,在
呼叫sub()方法時,必須使用g<name>來
參考
86
87
取得目錄資訊
• 若想知道目前工作目錄,或者切換工作目
錄,可以使用 os.getcwd() 或
os.chdir():
88
• 如果想得知指定的目錄下,有哪些檔案或
目錄,可以使用 os.listdir()
• 如果想要以惰性的方式處理,可以使用
os.scandir()
89
• 走訪目錄
90
• os.walk()會自行走訪子目錄
91
建立、修改、移除目錄
92
• 如果是有關於路徑的操作,Python 提供了
os.path 模組來解決相關的需求
– 路徑的組合
– 相對路徑轉為絕對路徑
– 取得檔案所在的目錄路徑等
– 路徑對應的檔案目或目錄資訊
93
94
95
96
97
• 想在工作目錄下搜尋檔案,例如想搜尋.py
檔案,可以使用 glob 模組
98
• glob 是個很簡單的模組,支援簡易的Glob
模式比對語法
• 比規則表示式簡單,常用於目錄與檔案名
稱的比對
99
100
101
URL規範
• URL中的U,早期代表Universal(萬用),
標準化之後代表Uniform(統一),因此目
前URL全名為Uniform Resource Locator
• URL的主要語法格式為:
102
• 一些協議名稱的例子有:
– ftp(檔案傳輸協定,File Transfer protocol)
– http(超文件傳輸協定,Hypertext Transfer
Protocol)
– mailto(電子郵件)
– file(特定主機檔案名稱)
103
• 協議特定部份(scheme-specific-part)的
格式依協議而定,通常會是:
104
• 請求 Web 應用程式主要是透過 HTTP 通訊
協定
• HTTP 定義了GET、POST、PUT、DELETE、
HEAD、OPTIONS、TRACE等請求方式
• 就使用urllib來說,最常運用GET與POST
105
GET 請求
106
POST 請求
107
• HTTP請求參數必須使用請求參數名稱與請
求參數值,中間以等號(=)表示成對關係
• 現在問題來了,如果請求參數值本身包括=
符號怎麼辦?又或許想發送的請求參數值
是「https://openhome.cc」這個值呢?
• 假設是GET請求,直接這麼發送是不行的:
108
保留字元
• 在URL規範定義了保留字元(Reserved
character),像是「:」、「/」、「?」、
「&」、「=」、「@」、「%」等字元
• 如果要在請求參數上表達URL中的保留字元,
必須在%字元之後以16進位數值表示方式,
來表示該字元的八個位元數值
109
• 在UTF-8的編碼下,中文多半會使用三個位
元組來表示
• 「林」這個字在UTF-8編碼下的三個位元組,
對應至16進位數值表示就是E6、9E、97
110
使用 urllib.request
• 當中有 request、parse、error 等模組
111
112
• 若 URL 對應之資源是份 HTML 文件,在
read() 取得 bytes 物件之後,可以使用
decode() 指定編碼
113
114
使用 urllib.parse
• 如果請求時需要附上請求參數
115
116
• 如果有個 URL,想要分別剖析出其中的協
定、主機、埠號等資訊
117
• 遇到相對路徑處理之時
118
使用 Request
119

Más contenido relacionado

Más de Justin Lin

Ch08 自訂標籤
Ch08 自訂標籤Ch08 自訂標籤
Ch08 自訂標籤Justin Lin
 
Ch07 使用 JSTL
Ch07 使用 JSTLCh07 使用 JSTL
Ch07 使用 JSTLJustin Lin
 
Ch06 使用 JSP
Ch06 使用 JSPCh06 使用 JSP
Ch06 使用 JSPJustin Lin
 
Ch05 Servlet 進階 API、過濾器與傾聽器
Ch05 Servlet 進階 API、過濾器與傾聽器Ch05 Servlet 進階 API、過濾器與傾聽器
Ch05 Servlet 進階 API、過濾器與傾聽器Justin Lin
 
Ch04 會話管理
Ch04 會話管理Ch04 會話管理
Ch04 會話管理Justin Lin
 
Ch03 請求與回應
Ch03 請求與回應Ch03 請求與回應
Ch03 請求與回應Justin Lin
 
Ch02 撰寫與設定 Servlet
Ch02 撰寫與設定 ServletCh02 撰寫與設定 Servlet
Ch02 撰寫與設定 ServletJustin Lin
 
CH1. 簡介 Web 應用程式
CH1. 簡介 Web 應用程式CH1. 簡介 Web 應用程式
CH1. 簡介 Web 應用程式Justin Lin
 
14. 進階主題
14. 進階主題14. 進階主題
14. 進階主題Justin Lin
 
13.並行、平行與非同步
13.並行、平行與非同步13.並行、平行與非同步
13.並行、平行與非同步Justin Lin
 
12. 除錯、測試與效能
12. 除錯、測試與效能12. 除錯、測試與效能
12. 除錯、測試與效能Justin Lin
 
10. 資料永續與交換
10. 資料永續與交換10. 資料永續與交換
10. 資料永續與交換Justin Lin
 
9. 資料結構
9. 資料結構9. 資料結構
9. 資料結構Justin Lin
 
8. open() 與 io 模組
8. open() 與 io 模組8. open() 與 io 模組
8. open() 與 io 模組Justin Lin
 
7. 例外處理
7. 例外處理7. 例外處理
7. 例外處理Justin Lin
 
6. 類別的繼承
6. 類別的繼承6. 類別的繼承
6. 類別的繼承Justin Lin
 
5. 從模組到類別
5. 從模組到類別5. 從模組到類別
5. 從模組到類別Justin Lin
 
4. 流程語法與函式
4. 流程語法與函式4. 流程語法與函式
4. 流程語法與函式Justin Lin
 
3.型態與運算子
3.型態與運算子3.型態與運算子
3.型態與運算子Justin Lin
 
1. Python起步走
1. Python起步走1. Python起步走
1. Python起步走Justin Lin
 

Más de Justin Lin (20)

Ch08 自訂標籤
Ch08 自訂標籤Ch08 自訂標籤
Ch08 自訂標籤
 
Ch07 使用 JSTL
Ch07 使用 JSTLCh07 使用 JSTL
Ch07 使用 JSTL
 
Ch06 使用 JSP
Ch06 使用 JSPCh06 使用 JSP
Ch06 使用 JSP
 
Ch05 Servlet 進階 API、過濾器與傾聽器
Ch05 Servlet 進階 API、過濾器與傾聽器Ch05 Servlet 進階 API、過濾器與傾聽器
Ch05 Servlet 進階 API、過濾器與傾聽器
 
Ch04 會話管理
Ch04 會話管理Ch04 會話管理
Ch04 會話管理
 
Ch03 請求與回應
Ch03 請求與回應Ch03 請求與回應
Ch03 請求與回應
 
Ch02 撰寫與設定 Servlet
Ch02 撰寫與設定 ServletCh02 撰寫與設定 Servlet
Ch02 撰寫與設定 Servlet
 
CH1. 簡介 Web 應用程式
CH1. 簡介 Web 應用程式CH1. 簡介 Web 應用程式
CH1. 簡介 Web 應用程式
 
14. 進階主題
14. 進階主題14. 進階主題
14. 進階主題
 
13.並行、平行與非同步
13.並行、平行與非同步13.並行、平行與非同步
13.並行、平行與非同步
 
12. 除錯、測試與效能
12. 除錯、測試與效能12. 除錯、測試與效能
12. 除錯、測試與效能
 
10. 資料永續與交換
10. 資料永續與交換10. 資料永續與交換
10. 資料永續與交換
 
9. 資料結構
9. 資料結構9. 資料結構
9. 資料結構
 
8. open() 與 io 模組
8. open() 與 io 模組8. open() 與 io 模組
8. open() 與 io 模組
 
7. 例外處理
7. 例外處理7. 例外處理
7. 例外處理
 
6. 類別的繼承
6. 類別的繼承6. 類別的繼承
6. 類別的繼承
 
5. 從模組到類別
5. 從模組到類別5. 從模組到類別
5. 從模組到類別
 
4. 流程語法與函式
4. 流程語法與函式4. 流程語法與函式
4. 流程語法與函式
 
3.型態與運算子
3.型態與運算子3.型態與運算子
3.型態與運算子
 
1. Python起步走
1. Python起步走1. Python起步走
1. Python起步走
 

11. 常用內建模組