Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

常用內建模組

905 views

Published on

《Python 3.5 技術手冊》第 11 章投影片

Published in: Software
  • Be the first to comment

常用內建模組

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

×