> For the complete documentation index, see [llms.txt](https://dinoin.gitbook.io/shi-py-bu-shi-pi/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://dinoin.gitbook.io/shi-py-bu-shi-pi/try-catch.md).

# Try-Catch

{% hint style="success" %}
可能有更好的選擇「with」

待進化！
{% endhint %}

## 基本使用

```python
try:
  a = int(input('輸入 0～9：'))
  if a>10:
      raise
  print(a)
except :
  print('有錯誤喔～')
else:
  print('沒有錯！繼續執行！')       # 完全沒錯才會執行這行
finally:
  print('管他有沒有錯，繼續啦！')    # 不論有沒有錯都會執行這行 
```

## 參考資料

> <https://dotblogs.com.tw/caubekimo/2018/09/17/145733>

## 拋出錯誤

{% code title="EX" %}

```python
raise ValueError("Only one of TIME or LOTs can be input!")
```

{% endcode %}

## 錯誤詳細資訊

```python
import sys
import traceback

try:
    test_func()
except Exception as e:
    cl, exc, tb = sys.exc_info()  # 取得Call Stack
    last_call_stack = traceback.extract_tb(tb)[-1]  # 取得Call Stack的最後一筆資料
    
    print('錯誤發生的檔案名稱', last_call_stack[0])
    # 錯誤發生的檔案名稱 /Users/dinoinchen/Utilites/Python-stock/test.py
    
    print('錯誤發生的行號', last_call_stack[1])
    # 錯誤發生的行號 6
    
    print('錯誤發生的函數名稱', last_call_stack[2])
    # 錯誤發生的函數名稱 test_func
    
    print('錯誤本身', last_call_stack[3])
    # 錯誤本身 raise RuntimeError("Test ERR!")
```

#### 另種方式獲取錯誤檔名與行數

```python
import traceback

try:
  ...
except Exception as e:
  print(traceback.format_exc())  # 獲取當前的堆疊蹤跡，顯示例外發生的檔案名和行數
```

## 錯誤列表參考

> <https://www.runoob.com/python/python-exceptions.html>

## 於FastAPI中，支持狀態的回傳

使用「HTTPException」傳出即可，不需要額外在外層包catch統一處理。

```python
from fastapi import HTTPException
raise HTTPException(status_code=404, detail="TEST ERROR! 測個錯誤!")
```

{% hint style="warning" %}
但這無法截獲「真正的意外」，萬一有意料外狀況仍會導致服務中止...目前除了每個API入口包try/catch之外，沒有測成功統一的介面處理。
{% endhint %}

> <https://fastapi.tiangolo.com/tutorial/handling-errors/>

#### \[舊方法]用額外catch擷取覆寫

{% code title="utility.functions.py: " %}

```python
def catch_exception_to_http_response(e):
    error_class = e.__class__.__name__  # 取得錯誤類型
    detail = e.args[0] if len(e.args[0])>0 else "Oops something is wrong!"  # 取得詳細內容
    cl, exc, tb = sys.exc_info()  # 取得Call Stack
    last_call_stack = traceback.extract_tb(tb)[-1]  # 取得Call Stack的最後一筆資料
    file_fame = last_call_stack[0]  # 取得發生的檔案名稱 >D:\Dinoin\workspace\yield-prediction-cip\api\Helper.py
    line_num = last_call_stack[1]  # 取得發生的行號 >99
    func_name = last_call_stack[2]  # 取得發生的函數名稱 >funcName
    print("File \"{}\", line {}, in {}: [{}] {}".format(file_fame, line_num, func_name, error_class, detail))
    print('錯誤本身:', last_call_stack[3]) # type=str
    raise HTTPException(status_code=400, detail=detail)
```

{% endcode %}

{% code title="main.py" %}

```python
from utility.functions import catch_exception_to_http_response as catch
  def main():
    try:
        return ...
    except Exception as e:
        raise catch(e)
```

{% endcode %}

> <https://fastapi.tiangolo.com/tutorial/handling-errors/> <https://steam.oxxostudio.tw/category/python/basic/try-except.html>
