"atexit" --- 退出處理函式
*************************

======================================================================

"atexit" 模組定義了註冊和註銷清理函式 (cleanup function) 的函式，這樣
的註冊函式會在直譯器正常終止時自動執行。"atexit" 按照這些函式註冊之*反
序*來運行這些函式；如果你有註冊 "A"、"B" 和 "C"，則在直譯器終止時它們
將按 "C"、"B"、"A" 的順序運行。

**注意：**當程式被一個不是來自 Python 的訊號終止、偵測到有 Python 嚴重
內部錯誤時或者 "os._exit()" 被呼叫時，透過此模組註冊的函式就不會被呼叫
。

**注意：**在清理函式中註冊或註銷函式的作用並未定義。

在 3.7 版的變更: 當與 C-API 子直譯器 (subinterpreter) 一起使用時，已註
冊函式對於它們所註冊的直譯器來說是區域的 (local)。

atexit.register(func, *args, **kwargs)

   將 *func* 註冊為要在終止時執行的函式。任何要傳遞給 *func* 的可選引
   數都必須作為引數傳遞給 "register()"。可以多次註冊相同的函式和引數。

   在程式正常終止時（例如呼叫 "sys.exit()" 或主要模組執行完成），所有
   已註冊函式都會依照後進先出的順序呼叫。這邊做的假設是較低階的模組通
   常會在較高階模組之前被引入，因此較低階模組必須在比較後面才被清理。

   如果在執行退出處理函式期間引發例外，則會列印回溯 (traceback)（除非
   引發 "SystemExit"）並儲存例外資訊。在所有退出處理函式都有嘗試運作過
   後，將重新引發最後一個引發的例外。

   該函式回傳 *func*，這使得可以將其作為裝飾器使用。

   警告:

     啟動新執行緒或從已註冊函式呼叫 "os.fork()" 可能會導致 Python 主要
     runtime 執行緒釋放執行緒狀態，而內部 "threading" 例程或新行程嘗試
     使用該狀態所形成的競態條件 (race condition)。這可能會導致崩潰
     (crash) 而不是完整關閉中止。

   在 3.12 版的變更: 嘗試在已註冊函式中啟動新執行緒或 "os.fork()" 新行
   程現在會導致 "RuntimeError"。

atexit.unregister(func)

   從在直譯器中止時會執行之函式串列中刪除 *func*。如果 *func* 先前未被
   註冊，則 "unregister()" 不會執行任何操作。如果 *func* 已被註冊多次
   ，則該函式在 "atexit" 呼叫堆疊 (call stack) 中的所有存在都會被刪除
   。會在註銷期間於內部使用相等性比較 ("==")，因此函式參照不需要具有匹
   配的識別性。

也參考:

  "readline" 模組
     "atexit" 用於讀取和寫入 "readline" 歷史檔案的一個不錯的範例。


"atexit" 範例
=============

以下的簡單範例示範了模組如何在被引入時以檔案來初始化計數器，並在程式終
止時自動儲存計數器的更新值，而不需要仰賴應用程式在終止時明確呼叫該模組
。

   try:
       with open('counterfile') as infile:
           _count = int(infile.read())
   except FileNotFoundError:
       _count = 0

   def incrcounter(n):
       global _count
       _count = _count + n

   def savecounter():
       with open('counterfile', 'w') as outfile:
           outfile.write('%d' % _count)

   import atexit

   atexit.register(savecounter)

位置引數和關鍵字引數也可以被傳遞給 "register()"，以便在呼叫時也傳遞給
已註冊函式：

   def goodbye(name, adjective):
       print('Goodbye %s, it was %s to meet you.' % (name, adjective))

   import atexit

   atexit.register(goodbye, 'Donny', 'nice')
   # 或是：
   atexit.register(goodbye, adjective='nice', name='Donny')

作為*裝飾器*使用：

   import atexit

   @atexit.register
   def goodbye():
       print('You are now leaving the Python sector.')

這只適用於可以不帶引數呼叫的函式。
