Python 入門指南 5.0

單元 21 - 非同步程式設計與認識標準程式庫

~~學習進度表~~

Python 已經內建大多數常用的功能,更多的功能都放在標準程式庫 (standard library) 裡

Standard Library

More

下表列出官方 Library Reference 整理的所有模組 (module) 分類

分類說明
Built-in Functions介紹所有內建函數。
Built-in Constants介紹所有內建常數,包括 False 、 True 、 None 等。
Built-in Types介紹所有內建型態及真假值計算,內建型態包括 int 、 float 、 complex 、迭代器、 list 、 tuple 、 range 、 str 、 bytes 、 bytearray 、 memoryview 、 set 、 frozenset 、 dict 及內容管理員、模組、類別、函數、方法等型態,真假值計算包括真值測試及布林運算等。
Built-in Exceptions介紹所有內建的例外類別。
Text Processing Services介紹文字相關處理模組,包括 string 、 re 、 difflib 、 textwrap 、 unicodedata 、 stringprep 、 readline 、 rlcompleter 等。
Binary Data Services介紹二進位資料處理模組,包括 struct 、 codecs 等。
Data Types介紹各種處理資料的資料型態模組,包括 datetime 、 zoneinfo 、 calendar 、 collections 、 collections.abc 、 heapq 、 bisect 、 array 、 weakref 、 types 、 copy 、 pprint 、 reprlib 、 enum 、 graphlib 等。
Numeric and Mathematical Modules介紹處理數字資料的模組,包括 numbers 、 math 、 cmath 、 decimal 、 fractions 、 random 、 statistics 等。
Functional Programming Modules介紹函數式程式設計相關模組,包括 itertools 、 functools 、 operator 等。
File and Directory Access介紹檔案及目錄處理的模組,包括 pathlib 、 os.path 、 fileinput 、 stat 、 filecmp 、 tempfile 、 glob 、 fnmatch 、 linecache 、 shutil 等。
Data Persistence介紹儲存資料相關模組,包括 pickle 、 copyreg 、 shelve 、 marshal 、 dbm 、 sqlite3 等。
Data Compression and Archiving介紹資料壓縮相關模組,包括 zlib 、 gzip 、 bz2 、 lzma 、 zipfile 、 tarfile 等。
File Formats介紹檔案格式相關模組,包括 csv 、 configparser 、 tomllib 、 netrc 、 plistlib 等。
Cryptographic Services介紹密碼處理相關模組,包括 hashlib 、 hmac 、 secrets 等。
Generic Operating System Services介紹一般作業系統相關模組,包括 os 、 io 、 time 、 argparse 、 getopt 、 logging 、 logging.config 、 logging.handlers 、 getpass 、 curses 、 curses.textpad 、 curses.ascii 、 curses.panel 、 platform 、 errno 、 ctypes 等。
Concurrent Execution介紹並行計算相關模組,包括 threading 、 multiprocessing 、 multiprocessing.shared_memory 、 concurrent 、 concurrent.futures 、 subprocess 、 sched 、 queue 、 contextvars 、 _thread 等。
Networking and Interprocess Communication介紹行程間通訊及網路處理相關模組,包括 asyncio 、 socket 、 ssl 、 select 、 selectors 、 signal 、 mmap 等。
Internet Data Handling介紹網路資料處理相關模組,包括 email 、 json 、 mailbox 、 mimetypes 、 base64 、 binascii 、 quopri 等。
Structured Markup Processing Tools介紹結構化標記處理工具,包括 html 、 html.parser 、 html.entities 、 xml 、 xml.etree.ElementTree 、 xml.dom 、 xml.dom.minidom 、 xml.dom.pulldom 、 xml.sax 、 xml.sax.handler 、 xml.sax.saxutils 、 xml.sax.xmlreader 、 xml.parsers.expat 等。
Internet Protocols and Support介紹對網路協定的支援,包括 webbrowser 、 wsgiref 、 urllib 、 urllib.request 、 urllib.response 、 urllib.parse 、 urllib.error 、 urllib.robotparser 、 http 、 http.client 、 ftplib 、 poplib 、 imaplib 、 smtplib 、 uuid 、 socketserver 、 http.server 、 http.cookies 、 http.cookiejar 、 xmlrpc 、 xmlrpc.client 、 xmlrpc.server 、 ipaddress 等。
Multimedia Services介紹多媒體相關模組,包括 wave 、 colorsys 等。
Internationalization介紹國際化相關模組,包括 gettext 、 locale 等。
Program Frameworks介紹程式框架相關模組,包括 turtle 、 cmd 、 shlex 等。
Graphical User Interfaces with Tk介紹圖形應用的 Tk 模組,包括 tkinter 、 tkinter.colorchooser 、 tkinter.font 、 tkinter.simpledialog 、 tkinter.messagebox 、 tkinter.scrolledtext 、 tkinter.dnd 、 tkinter.ttk 、 tkinter.tix 等。
Development Tools介紹程式發展相關工具,包括 typing 、 pydoc 、 doctest 、 unittest 、 unittest.mock 、 unittest.mock 、 2to3 、 test 、 test.support 、 test.support.socket_helper 、 test.support.script_helper 、 test.support.bytecode_helper 、 test.support.threading_helper 、 test.support.os_helper 、 test.support.import_helper 、 test.support.warnings_helper 等。
Debugging and Profiling介紹除錯及效能分析相關模組,包括 bdb 、 faulthandler 、 pdb 、 cProfile 、 profile 、 timeit 、 trace 、 tracemalloc 等。
Software Packaging and Distribution介紹軟體套件及發佈相關工具,包括 distutils 、 ensurepip 、 venv 、 zipapp 等。
Python Runtime Services介紹執行期間相關服務,包括 sys 、 sysconfig 、 builtins 、 __main__ 、 warnings 、 dataclasses 、 contextlib 、 abc 、 atexit 、 traceback 、 __future__ 、 gc 、 inspect 、 site 等。
Custom Python Interpreters介紹直譯器相關工具,包括 code 、 codeop 。
Importing Modules介紹引入模組相關工具,包括 zipimport 、 pkgutil 、 modulefinder 、 runpy 、 importlib 、 importlib.resources 、 importlib.resources.abc 、 importlib.metadata 、 sys.path 等。
Python Language Services介紹 Python 語言相關工具,包括 ast 、 symtable 、 token 、 keyword 、 tokenize 、 tabnanny 、 pyclbr 、 py_compile 、 compileall 、 dis 、 pickletools 等。
MS Windows Specific ServicesMS-Windows 特定服務,包括 msvcrt 、 winreg 、 winsound 。
Unix Specific ServicesUNIX 特定服務,包括 posix 、 pwd 、 grp 、 termios 、 tty 、 pty 、 fcntl 、 resource 、 syslog 。

每個模組都有為數不等的類別 (class) 、函數 (function) 、常數 (constant) 等定義,需要時可以直接用關鍵字 (keyword) import 引入到自己的程式中使用。

這裡先介紹關鍵字 asyncawait 會用到的 asyncio 模組,主要用在非同步程式設計 (asynchronous programming) 方面,雖然說非同步程式設計的複雜對初學者會有有些複雜,下面我們盡可能以初學者能理解的方式來解釋。

基本上,程式執行的時候是按照程式檔案,從上而下一行程式碼接著一行程式碼去執行,這時候會一直佔用 CPU 資源,但是有時候程式沒辦法及時處理,像是連到某一個網站要求資料,必須等網站回傳資料,如果網站伺服器計算需要時間,這時候我們的程式就會一直佔用 CPU 資源,直到網站回傳資料。

非同步程式設計就是在程式中告訴作業系統,這邊的程式需要等待, CPU 資源可以先分配給其他程式使用,這樣作業系統就會合理去使用 CPU 資源,進而提高程式運作的效率。

下面用個簡單例子來說明需要等待跟不需要等待的差別

 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
# 引入標準程式庫中的 asyncio
import asyncio

# 定義協程函數
async def main():
    # 等待一秒
    await asyncio.sleep(1)
    # 顯示提示訊息
    print("未輸入...")

# 取得使用者輸入的迴圈
while True:
    # 取得使用者輸入
    user = input("請輸入:")
    # 迴圈結束條件
    if user == "quit":
        break
    # 判斷使用者是否有輸入
    if user:
        # 印出使用者輸入
        print(user)
    else:
        # 等待一秒印出提示訊息
        asyncio.run(main())

# 檔名: std_demo01.py
# 說明:《Python入門指南》的範例程式
# 網站: http://kaiching.org
# 作者: 張凱慶
# 時間: 2023 年 5 月

處理非同步程式設計,要先在第 2 行引入標準程式庫中的 asyncio

 2
import asyncio

然後要定義協程 (coroutine) 函數

 5
 7
 9
async def main():
    await asyncio.sleep(1)
    print("未輸入...")

協程函數是在關鍵字 def 之前加上 async

 5
async def main():

然後在協程函數中加入關鍵字 awaitawait 後面接的是可能需要等待的程式碼,這裡用的是 asyncio.sleep(1) ,表示會睡眠一秒

 9
    await asyncio.sleep(1)

也就是說,程式告訴作業系統,在程式睡眠一秒的時間內,作意系統可以把這一秒的 CPU 資源分配給其他程式使用。

協程函數最底下是印出「未輸入」的提示訊息

 7
    print("未輸入...")

然後下面是用一個典型 while True 迴圈 (loop) 來取得使用者輸入

12
14
16
17
19
21
22
24
while True:
    user = input("請輸入:")
    if user == "quit":
        break
    if user:
        print(user)
    else:
        asyncio.run(main())

第 14 行利用內建函數 input() 取得使用者輸入

14
    user = input("請輸入:")

input() 的參數 (parameter) 為印出的提示訊息,這裡也就是提示在冒號後進行輸入,然後輸入的內容會以字串 (string) 形式指派到變數 (variable) user 中,其實 input() 函數就是一個會一直佔用 CPU 資源的函數, input() 會一直等到使用者按下 Enter 鍵才會結束。

接下來判斷使用者是否輸入 quit ,如果使用者輸入 quit 就會中斷 while True 迴圈,等同結束程式執行

16
17
    if user == "quit":
        break

然後判斷使用者是否有輸入,如果使用者按下鍵盤上除了 Enter 之外的按鍵, user 就會有值,回傳 True ,底下會印出使用者輸入

19
21
    if user:
        print(user)

反倒如果使用者直接按下 Enter 鍵, input() 就會直接回傳空字串,空字串回傳 False ,因此會跳到 else 的部分去執行協程函數 main()

22
24
    else:
        asyncio.run(main())

執行這個程式,一開始就是無限等待使用者輸入

$ python std_demo01.py
請輸入: █

使用者輸入文字,按下 Enter 鍵就會在下一行顯示使用者輸入的文字

請輸入: Hello
Hello
請輸入: █

如果直接按下 Enter 鍵,就會進入 main() 等待一秒

請輸入:

接著印出提示訊息,接者跳回輸入提示

未輸入...
請輸入: █

必須打入 quit 才能讓程式正常結束

請輸入: quit
$

以上的例子就是 input() 會持續佔用 CPU 資源等待使用者按下鍵盤上的按鍵,協程函數 main() 會自動睡眠一秒,這一秒期間並不佔用 CPU 資源。

接下來繼續看到幾個標準程式庫中的例子,基本上所有內建識別字 (identifier) 都屬於標準程式庫的定義,例如內建型態跟內建函數,說到內建函數,其中我們最常用到的 print() ,第一個參數是不限個數參數的序對 (tuple) ,也就是可以輸入任意個數的參數值,另外還有關鍵字引數 (keyword argument) sepend

sep 的預設值是空格 " " ,至於 end 的預設值則是斷行符號 "\n" ,以下舉一個例子,利用 input 輸入得到 number ,然後在 print() 印出來

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
# 使用者輸入
number = int(input("請輸入:"))
# 印出使用者輸入
print(number, number, sep="...", end="..")
print(number, end=".")
print(number)

# 檔名: std_demo02.py
# 說明:《Python入門指南》的範例程式
# 網站: http://kaiching.org
# 作者: 張凱慶
# 時間: 2023 年 5 月

第 4 行,第一次使用 print() 是印出兩個 number ,中間以 "..." 分隔,結尾則是 ".."

 4
print(number, number, sep="...", end="..")

第 5 行,第二次使用 print() 印出一個 number ,並且以 "." 結尾

 5
print(number, end=".")

第 6 行,第三次使用 print() 印出一個 number ,沒有設定 end 所以預設印出 "\n"

 6
print(number)

由於第三次呼叫 print() 才印出 "\n" ,因此所有內容會印在同一行

$ python std_demo02.py
請輸入:12
12...12..12.12
$

datetime 是標準程式庫中處理時間日期的模組,以下程式示範印出現在時間

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
# 從標準程式庫 datetime 引入 datetime
from datetime import datetime

# 取得現在時間
now = datetime.now()
# 格式化現在時間字串
now_str = str(now.hour) + ":" + str(now.minute) + ":" + str(now.second)
# 印出現在時間
print(now_str)

# 檔名: std_demo03.py
# 說明:《Python入門指南》的範例程式
# 網站: http://kaiching.org
# 作者: 張凱慶
# 時間: 2023 年 5 月

先從 datetime 引入 datetime

 2
print(number)

datetime 是處理日期時間的物件。

利用 datetimenow() 會回傳現在的日期時間物件

 5
now = datetime.now()

然後利用 hourminutesecond 屬性 (attribute) 組成以冒號區隔的時間字串

  7
now_str = str(now.hour) + ":" + str(now.minute) + ":" + str(now.second)

最後印出時間字串

  9
print(now_str)

執行結果如下

$ python std_demo03.py
11:26:58
$

最後我們介紹關鍵字 withwith 主要用在輸入輸出的部分,舉例如下

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
# 計數變數
count = 1
# 進行檔案寫入
with open('demo.txt', 'w') as f:
    # 依次寫入第幾行
    while count < 6:
        s = "第" + str(count) + "行\n"
        f.write(s)
        count += 1
# 進行檔案讀取
with open('demo.txt', 'r') as f:
    # 依次印出檔案中的每一行
    for s in f.readlines():
        print(s, end="")

# 檔名: std_demo04.py
# 說明:《Python入門指南》的範例程式
# 網站: http://kaiching.org
# 作者: 張凱慶
# 時間: 2023 年 5 月

第 4 行先用 with 搭配內建函數 open() 開啟檔案,注意這裡 open() 第一個參數為檔案名稱,第二個參數是模式, 'w' 表示寫入

  4
with open('demo.txt', 'w') as f:

關鍵字 as 後面接的是變數名稱,這裡採用 f ,意思是說利用 open() 開啟 demo.txt 檔案,模式是寫入,因此如果沒有這個檔案就會建立這個檔案,結果變數 f 會連結到 open() 回傳的檔案物件, with 底下縮排的程式碼就是進行檔案處理

  6
  7
  8
  9
    while count < 6:
        s = "第" + str(count) + "行\n"
        f.write(s)
        count += 1

這段檔案處理的程式碼的重點在第八行

  8
        f.write(s)

檔案物件的 write() 將參數字串寫入到檔案之中,由於字串結尾都已加入段行符號 "\n" ,因此一次寫入就是一行,這裡一共會寫入五行。

關鍵字 with 其實是處理輸入輸出的語法糖,因為處理輸入輸出要先建立輸入輸出的物件,最後處理完畢要用 close() 關閉輸入輸出物件,用 with 的好處是會自動關閉,我們就不需要考慮是否關閉的問題。

底下第二個 with 則是重新開啟 demo.txt ,模式 'r' 表示讀取

11
13
14
with open('demo.txt', 'r') as f:
    for s in f.readlines():
        print(s, end="")

然後利用檔案物件的 readlines() 方法印出檔案中的每一行內容,執行結果如下

$ python std_demo04.py
第1行
第2行
第3行
第4行
第5行
$

基礎篇至此把 Python 所有關鍵字都簡略介紹用法,接下來我們開始介紹用 Python 開發軟體的方式,帶領讀者開發 GUI 的編密碼軟體,藉此介紹更多的 Python 寫程式技巧囉!

中英文術語對照
非同步程式設計asynchronous programming
屬性attribute
類別class
協程coroutine
常數constant
函數function
識別字identifier
關鍵字keyword
關鍵字引數keyword argument
迴圈loop
參數parameter
模組module
標準程式庫standard library
字串string
序對tuple
變數variable
重點整理
1. Python 的標準程式庫中有非常多常用功能,自己寫程式的時候可以直接引入使用。
2. 非同步程式設計是不持續佔用 CPU 資源的程式設計模式。
3. 內建識別字都屬於標準程式庫的定義。
4. 內建函數 pinrt() 可以接受多個參數,其中可以用關鍵字引數 sep 設定參數的分隔方式, end 設定最後結尾符號。
5. 標準程式庫中的 datetime 用來處理時間、日期。
6. 關鍵字 with 可用來進行輸入輸出的工作,內建函數 open() 可用來開啟檔案。
問題與討論
1. 為甚麼要有標準程式庫?程式要什麼功能不能全部自己開發嗎?
2. 什麼是協程函數?
3. 檔案處理可以不用關鍵字 with 嗎?用 with 有什麼方便的地方?
練習
1. 標準程式庫中的 re 用來處理正規運算式,寫一個程式 exercise2101.py ,利用 research() 來尋找英文句子中是否存在 no參考程式碼
2. 標準程式庫中的 calendar 可以顯示月曆,寫一個程式 exercise2102.py ,先設定星期天為一個星期的第一天,然後印出月曆。 參考程式碼
3. 標準程式庫中的 math 有很多跟數學相關的常數及函數,寫一個程式 exercise2103.py ,利用 math 中的 gcd() 計算參數的最大公因數,然後再利用 isqrt() 判斷參數是否為平方,最後印出 pi 值。 參考程式碼
4. 標準程式庫中的 decimal 用來處理浮點數精確度的問題,寫一個程式 exercise2104.py ,利用 decimal 中的 Decimal 印出 3.140.111.0 等浮點數。 參考程式碼
5. 標準程式庫中的 random 用來處理擬隨機數,寫一個程式 exercise2105.py ,利用 random 中的 randint() 印出 0910192029 之間的隨機整數。 參考程式碼
6. 標準程式庫中有兩種判斷現在作業系統的方式,分別是利用 os 中的 namesys 中的 platform ,寫一個程式 exercise2106.py ,在命令列中印出這兩個常數值。 參考程式碼
7. 標準程式庫中的 os 用來處理跟作業系統有關的項目,寫一個程式 exercise2107.py ,利用 os 中的 getcwd() 取得現在的命令列路徑。 參考程式碼
8. 標準程式庫中的 doctest 可以在文件字串中寫測試程式,然後放在執行部分進行測試,寫一個程式 exercise2108.py ,利用之前寫過的練習加入具有測試程式碼的文件字串,然後在執行部分利用 doctesttestmod() 進行測試。 參考程式碼
9. 標準程式庫中的 unittest 可以做單元測試,寫一個程式 exercise2109.py ,引入上題的定義,然後定義繼承自 unittestTestCase 的測試類別,執行部分呼叫 unittestmain()參考程式碼
10. 標準程式庫中的 sys 有許多根直譯器相關的功能,寫一個程式 exercise2110.py ,利用 sysmaxsize 取得直譯器能處理的最大整數值, version 取得現在的直譯器版本, getsizeof() 計算參數所所佔的記憶體位元組數。 參考程式碼

上一頁 單元 20 - 文件字串
回 Python 入門指南 5.0 首頁
下一頁 軟體開發篇
回 Python 教材首頁
回程式語言教材首頁