Se ha denunciado esta presentación.
Se está descargando tu SlideShare. ×

11. 常用內建模組

Anuncio
Anuncio
Anuncio
Anuncio
Anuncio
Anuncio
Anuncio
Anuncio
Anuncio
Anuncio
Anuncio
Anuncio
Próximo SlideShare
常用內建模組
常用內建模組
Cargando en…3
×

Eche un vistazo a continuación

1 de 119 Anuncio

Más Contenido Relacionado

Más reciente (20)

Anuncio

11. 常用內建模組

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

×