隨手養成 Python 好習慣-勤註解、善用自動文件產生工具 Sphinx

Last updated on  Jan 11, 2021  in  Python 模組/套件推薦 , Python 程式設計 - 高階  by  Amo Chen  ‐ 4 min read

不管是何種程式語言都有註解的需求,而好的程式開發人員都必須具備勤寫註解的美德。

寫註解不僅是為了幫助自己了解程式的相關細節,也是為了能夠讓他人方便於一起參與開發、維護的重要步驟。

正因為現今的系統架構越來越繁雜,而開發人員的大腦記憶能力有限,當他們持續在開發新功能的同時,其實就已經在慢慢淡忘舊功能的實作細節。

特別是每當發現舊功能需要進行維護與除錯時,往往已經過一段時日,開發人員所存的印象早就所剩無幾,更遑論能夠迅速達成維護與除錯的目標。這些現象在程式開發過程屢見不鮮,因此養成撰寫註解的習慣格外重要。

而每個組織對於註解的規定有所不同,但若是對於初學 Python 程式的新進入者而言,可以參考 Google Python Style Guide 對於註解的規範的章節(連結)。

此外,除了註解,通常文件(documentation)也是必備的產出之一,這些細節都可在 GitHub 上的知名專案可見一斑(如 Django , D3 等)。 但基於 DRY(Don’t Repeat Yourself) 原則,我們希望可以在撰寫註解的同時,也一併完成文件的撰寫(相信有許多程式設計師厭惡撰寫文件),因此本文將介紹如何利用 Sphinx 將 Python 中的註解自動萃取出來,並且自動地產生一份文件供人參考。

Sphinx 是一套相當成熟的文件產生工具,除了能夠用來撰寫書籍與網站之外,也能夠用來自動化將程式碼中的註解萃取出來並變成一份文件,目前支援 Python, Javascript, C/C++,同時也有許多開發者貢獻的的套件

接下來,將分步驟解說如何使用 Sphinx 自動化文件產生工具。

本文環境

在開始本文前,請先確認有 Python 的執行環境,並請安裝以下 Python 套件:

建立專案資料夾結構

首先,我們需要建立一個類似以下的資料夾結構,用來存放我們用 Sphinx 產生的文件資料夾以及我們的 Python 程式碼。

python_project/
├── doc/
└── src/

接下來,我們用以下指令在 doc/ 資料夾中建立 Sphinx 專案,過程中 Sphinx 會詢問若干選項,各位可以依照需求進行選擇(本文主要選擇將 build/source/ 資料夾分開)。

sphinx-quickstart doc

執行完上述的指令後,我們的資料夾結構會如下所示:

python_project/
├── doc/
│   ├── build
│   └── source
└── src/

其中 doc/source/ 裡面存放著我們撰寫的文件與 Sphinx 設定檔,我們會在接下來的步驟中進行教學。

變更 doc/source/conf.py 設定檔

由於我們必須設定讓 Sphinx 可以自動從 src/ 資料夾內的 Python 程式內的註解萃取出來,並且做成一份文件,因此我們需要變更 doc/source/conf.py 設定檔內的設定。

doc/source/conf.py 設定檔以文字編輯器打開後,約莫在一開始的地方,先試著找到以下的註解說明:

# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.

接著在上述的註解下方加入以下設定,如此一來 Sphinx 就能夠讀取到 src/ 資料夾內的 Python 程式檔案:

import os
import sys
sys.path.insert(0, os.path.abspath('../../src/'))

以及,確保 extensions 變數有添加 autodoc 擴充,例如:

# Add any Sphinx extension module names here, as strings. They can be
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
# ones.
extensions = ['sphinx.ext.autodoc']

如果喜歡 Google 的 Python 註解風格 的話,可以多增加 1 個擴充在 extensions 中:

extensions = ['sphinx.ext.autodoc', 'sphinx.ext.napoleon']

開始於 src/ 內撰寫 Python 程式,並且加入 reStructedText 格式的註解

例如本文用以下 Python 程式碼作為示範(Hello.py):

"""
A simple module for printing "Hello"

.. module:: Hello

.. moduleauthor:: Amo

"""

def print_hello_with_name(name):
    """This function prints hello with a name

    Args:
       name (str):  The name to use.

    Returns:
       int.  The return code::

          0 -- this always return 0

    Raises:
       AttributeError, KeyError

    A really simple function. Really!

    >>> print_hello_with_name('foo')
    Hello, foo

    """
    print('Hello', name)
    return 0

在上述的程式碼註解中,一開始我們用 .. module:: Hello 說明 module 名稱為 Hello,並且加上 .. moduleauthor:: Amo 標明作者為 Amo, 最後在 print_hello_with_name 函式底下以 docstring 的方式,簡單說明函式的用途等相關資訊。

p.s. 更多的語法可以參考官方文件

編輯 doc/source/index.rst

doc/source/index.rst 是 Sphinx 預設作為首頁(或索引)的檔案,因此我們必須在這個首頁中加入我們需要被引入的文件名稱,以本文為例則是加入一個名為 Hello 的說明文件(注意:Hello 與 .. toctree:: 區塊需隔一行):

Contents:

.. toctree::
   :maxdepth: 2

   Hello

上述代表我們會在首頁中引入 Hello.rst 的內容(Sphinx 預設省略 rst 副檔名),因此我們也必須在 doc/source/ 資料夾中新增一個名為 Hello.rst 的檔案。

撰寫 Hello.rst

最後我們必須在 Hello.rst 中指明與哪個存在於 src/ 資料夾內的程式有關,例如以下的 Hello.rst 範例,就是利用 .. automodule:: Hello 說明要將 Hello.py 中的註解說明放入文件中,同時指明 Hello module 中有一個稱為 print_hello_with_name 的成員,更多用法同樣可以參考官方文件

documentation for "Hello"
=========================

.. automodule:: Hello
   :noindex:
   :members:
   :undoc-members:
   :show-inheritance:

除了手工撰寫之外,也可以用以下指令讓 Sphinx 掃描 src 資料夾,並自動產生所有的 .rst 檔到 doc/source 資料夾中,接著再進行編輯撰寫文件即可:

$ cd python_project
$ sphinx-apidoc -o doc/source src

p.s. 記得在自動產生的 .rst 檔裡的 .. automodule:: 底下加上 :noindex: 代表一切文件內容以 Hello.py 裡的為準

產生文件

當上述 5 個步驟都做完之後,我們就能夠在 doc/ 資料夾內輸入以下指令產生文件:

make html

完成之後,doc/build/html/ 資料夾內會產生 html 格式的文件,只要利用瀏覽器開啟即可,範例畫面如下圖:

以上, Happy coding !

References

https://www.sphinx-doc.org/en/master/index.html

https://pythonhosted.org/an_example_pypi_project/sphinx.html

https://google.github.io/styleguide/pyguide.html

對抗久坐職業傷害

研究指出每天增加 2 小時坐著的時間,會增加大腸癌、心臟疾病、肺癌的風險,也造成肩頸、腰背疼痛等常見問題。

然而對抗這些問題,卻只需要工作時定期休息跟伸展身體即可!

你想輕鬆改變現狀嗎?試試看我們的 PomodoRoll 番茄鐘吧! PomodoRoll 番茄鐘會根據你所設定的專注時間,定期建議你 1 項辦公族適用的伸展運動,幫助你打敗久坐所帶來的傷害!

贊助我們的創作

看完這篇文章了嗎? 休息一下,喝杯咖啡吧!

如果你覺得 MyApollo 有讓你獲得實用的資訊,希望能看到更多的技術分享,邀請你贊助我們一杯咖啡,讓我們有更多的動力與精力繼續提供高品質的文章,感謝你的支持!