---
# System prepended metadata

title: 寫程式的小技巧
tags: [Python]

---

地質背景的學生要進入地震學的領域，其實對電腦和程式(Programming)工具並不是很了解。在寫程式來進行資料處理的時候，有些小技巧可以幫助你把工作做得更好，我們整理了以下這些實用的概念。
## 不輸出檔案的試運行 Dry run
當我們需要執行行數較多的程式輸出檔案的時候，很容易會因為一些小bug而導致結果出錯，如果每次都要產生檔案、刪除檔案，會花費很多時間除錯。因此**在測試的時候可以先把最後寫入檔案的那行指令註解掉，或是換成print替代文字**，如此一來就可以先專心檢查各種資料處理的狀況。
你可以在寫Python程式的時候多加一個DRY_RUN的選項，減少錯誤發生的機會。

## 抓出錯誤 Error catching & Logging
在批次執行程式時，我們常常會使用try/except來讓部分資料出錯時仍能繼續執行下去。為了取得更詳細的錯誤資料，我們可以**像沒有try/except時輸出traceback的訊息**。

舉例來說：
```python=
import traceback

def do_stuff():
    raise Exception("test exception")

try:
    do_stuff()
except Exception:
    print(traceback.format_exc())
```
在執行的時候就會產生下面的訊息：
```py
traceback (most recent call last):
  File "main.py", line 9, in <module>
    do_stuff()
  File "main.py", line 5, in do_stuff
    raise Exception("test exception")
Exception: test exception
```

但如果只把錯誤狀況print到console，這個錯誤訊息很容易就會被淹沒在茫茫訊息海中。
因此更好的辦法是**在執行過程中輸出一個紀錄檔(log file)**，就可以在結束後檢視執行的狀況。

Python有個內建的模組叫logging，裡面就提供了撰寫紀錄檔所需要的功能。
```python=
import logging

# Configure logging
logging.basicConfig(level=logging.DEBUG,
                    format='%(asctime)s - %(levelname)s - %(message)s',
                    handlers=[
                        logging.FileHandler("debug.log"),
                        logging.StreamHandler()
                    ])

# Create a logger
logger = logging.getLogger(__name__)

# Log messages
logger.debug("This is a debug message")
logger.info("This is an info message")
logger.warning("This is a warning message")
logger.error("This is an error message")
logger.critical("This is a critical message")
```
* logger的設定包含紀錄的層級(level)以及格式，可以搭配你想要使用的log message層級。

## 統一風格和檢查 Formatting and Linting
為了方便閱讀以及在多人協作的時候確保編寫格式的一致，寫程式的人會制定一個編寫的風格指南，例如什麼時候要空格，什麼時候要換行。以python來說，最多人使用的風格指南是一個名為[PEP8](https://cflin.com/wordpress/603/pep8-python%E7%B7%A8%E7%A2%BC%E8%A6%8F%E7%AF%84%E6%89%8B%E5%86%8A)的原則，不過我們只要知道有什麼工具可以幫我們編排就好。
### Black formatter
[black](https://github.com/psf/black)是python最多人使用的格式化工具，可以在命令列執行，也有vscode擴充元件可以使用。
### isort
isort是專門整理import的工具，只有vscode擴充元件。

### pylint
formatter只會檢查格式，linter則會檢查語法的邏輯和合理性，例如變數的型別是否能被確保、所有定義過的變數和函數都會被呼叫到等等。這對於寫程式沒有嚴謹習慣的人來說會需要一點時間熟悉，但可以一定程度減少出錯的機會。

---

> 撰寫複雜套件的基礎概念：以functional programming的原則來建構基本元件，並利用物件導向(Object-oriented)的架構來提高擴充性。

## 函數化程式設計 Functional Programming
大部分初學或自學程式的人都會習慣把要執行的指令一行接一行全部寫在一起。但當你的專案越來越大，或需要產生一些變化時，就得花上許多時間手動更改內容，還很可能出錯。
你除了可以善用變數(variable)來減少更改的次數，還可以透過重複使用函數(function)來簡化你的程式。

## 物件導向程式設計 Object-oriented Programming
(e.g. Python Class)