iT邦幫忙

0

Day 15:新增資料功能——將使用者輸入的資料保存起來

  • 分享至 

  • xImage
  •  

一、前言

在第十四天的學習中,我已經使用 Streamlit 建立健康紀錄表單,讓使用者可以輸入日期、喝水量、睡眠時間、運動時間、蔬菜水果攝取情況與備註,並在送出表單後查看輸入結果。

然而,目前的系統仍然存在一個問題:使用者送出的資料還沒有真正保存起來。

如果每次輸入完資料,都只能在畫面上看到結果,之後卻無法再次查詢,就很難持續追蹤個人的健康習慣。因此,今天的目標是將表單與資料保存功能整合,讓使用者每次新增健康紀錄時,系統都能將資料寫入檔案,並在後續使用時重新讀取。

今天將運用先前學習的 Dictionary、Pandas、CSV 與 Streamlit 表單,完成健康習慣追蹤系統的第一個資料新增功能。

二、了解資料新增的流程

在實際撰寫程式之前,需要先整理使用者輸入資料後,系統應該執行哪些步驟。

本次資料新增功能的流程如下:

使用者開啟健康紀錄表單。

填寫日期、喝水量、睡眠時間、運動時間及其他資訊。

點擊送出按鈕。

系統取得表單中的資料。

將資料整理成統一的資料結構。

將資料新增至 CSV 檔案。

顯示新增成功的訊息。

這樣的流程可以讓資料輸入、資料整理與資料保存各自具有明確的工作。

此外,系統也需要考慮第一次使用時尚未建立 CSV 檔案的情況,以及檔案已經存在、需要繼續加入新紀錄的情況。

三、將表單資料整理成 Dictionary

在第九天的學習中,我已經認識 Python 的 List 與 Dictionary,並了解 Dictionary 可以透過鍵值對的方式,將不同欄位與對應資料組合起來。

例如,一筆健康紀錄可以表示為:

health_record = {
"date": "2026-10-26",
"water_ml": 1800,
"sleep_hours": 7.5,
"exercise_minutes": 30,
"vegetables_fruits": True,
"notes": "今天有散步"
}

其中,每個鍵都代表一個資料欄位,而對應的值則是使用者輸入的內容。

這種資料結構有幾個優點:

每個欄位都有明確名稱,方便辨識。

不同型態的資料可以放在同一筆紀錄中。

後續可以直接轉換成 Pandas DataFrame。

可以搭配 CSV 或 SQLite 保存資料。

因此,在新增資料功能中,我會先將表單內容整理成 Dictionary,再交給資料保存的程式處理。

四、使用 Pandas 將資料保存至 CSV

在第十一天的學習中,我已經了解 CSV 可以用來保存表格資料,也學習了如何使用 Pandas 讀取與寫入 CSV 檔案。

今天將運用這個方法,將健康紀錄保存至 health_records.csv。

  1. 匯入需要的套件

import pandas as pd
from pathlib import Path

其中,pandas 負責處理表格資料,而 Path 則可以協助檢查檔案是否存在。

  1. 建立資料保存函式

import pandas as pd
from pathlib import Path

FILE_PATH = Path("health_records.csv")

def save_health_record(record):
new_record = pd.DataFrame([record])

if FILE_PATH.exists():
    old_records = pd.read_csv(FILE_PATH)

    all_records = pd.concat(
        [old_records, new_record],
        ignore_index=True
    )
else:
    all_records = new_record

all_records.to_csv(
    FILE_PATH,
    index=False,
    encoding="utf-8-sig"
)

這個函式會先將單筆 Dictionary 轉換成 DataFrame,再檢查 CSV 檔案是否已經存在。

如果檔案已存在,程式就會讀取原有紀錄,並使用 pd.concat() 將新資料加入;如果檔案不存在,則直接使用新資料建立檔案。

最後,透過 to_csv() 將完整資料寫入 CSV。

其中,index=False 表示不額外寫入 Pandas 的索引欄位,而 encoding="utf-8-sig" 則有助於讓 CSV 在常見的試算表軟體中正確顯示中文。

需要注意的是,這個基本版本每次新增資料時都會重新寫入整份 CSV,適合目前的小型練習專案。當資料量增加,或需要更完善的資料一致性與查詢功能時,可以再改用 SQLite。

五、整合 Streamlit 表單與資料保存功能

接下來,將第十四天的表單與剛才建立的保存函式整合,讓使用者送出資料時,系統可以直接保存紀錄。

請將 app.py 的內容改成以下程式碼:

import streamlit as st
import pandas as pd
from pathlib import Path
from datetime import date

FILE_PATH = Path("health_records.csv")

def save_health_record(record):
new_record = pd.DataFrame([record])

if FILE_PATH.exists():
    old_records = pd.read_csv(FILE_PATH)

    all_records = pd.concat(
        [old_records, new_record],
        ignore_index=True
    )
else:
    all_records = new_record

all_records.to_csv(
    FILE_PATH,
    index=False,
    encoding="utf-8-sig"
)

st.title("個人健康習慣追蹤系統")

st.write("請填寫今天的健康習慣紀錄。")

with st.form("health_record_form"):

record_date = st.date_input(
    "紀錄日期",
    value=date.today()
)

water = st.number_input(
    "今日喝水量(毫升)",
    min_value=0,
    max_value=10000,
    value=1500,
    step=100
)

sleep = st.number_input(
    "今日睡眠時間(小時)",
    min_value=0.0,
    max_value=24.0,
    value=8.0,
    step=0.5
)

exercise = st.number_input(
    "今日運動時間(分鐘)",
    min_value=0,
    max_value=1440,
    value=0,
    step=10
)

vegetables_fruits = st.checkbox(
    "今天有攝取蔬菜水果"
)

notes = st.text_area(
    "今日備註",
    placeholder="記錄今天的生活情況"
)

submitted = st.form_submit_button(
    "儲存健康紀錄"
)

if submitted:
health_record = {
"date": record_date.isoformat(),
"water_ml": water,
"sleep_hours": sleep,
"exercise_minutes": exercise,
"vegetables_fruits": vegetables_fruits,
"notes": notes.strip()
}

try:
    save_health_record(health_record)
    st.success("健康紀錄已成功保存!")
    st.write("本次新增的資料:")
    st.json(health_record)

except (OSError, pd.errors.ParserError) as error:
    st.error("資料保存失敗,請檢查檔案狀態與執行權限。")

完成後,在終端機執行:

python -m streamlit run app.py

如果使用 python3,也可以執行:

python3 -m streamlit run app.py

成功啟動後,填寫表單並點擊「儲存健康紀錄」,系統就會將本次輸入的資料保存至 CSV 檔案。

程式中的重要概念

https://ithelp.ithome.com.tw/upload/images/20261026/20178903lo2614kpxR.png

這段程式使用 try...except 處理部分常見的檔案操作錯誤,讓系統在遇到檔案讀寫問題時可以顯示提示,而不是直接呈現完整的錯誤追蹤資訊。

不過,這仍是基本的錯誤處理方式,並未涵蓋所有可能的例外情況。若發生其他未處理的錯誤,仍需要根據終端機訊息進一步除錯。

六、確認資料是否真的保存成功

完成新增功能後,不能只確認畫面是否顯示成功訊息,還需要檢查資料是否真的寫入檔案。

可以使用以下程式讀取 CSV:

import pandas as pd

records = pd.read_csv("health_records.csv")

print(records)

執行後,應該可以看到剛才新增的健康紀錄。

也可以查看檔案所在的資料夾,確認是否已經產生 health_records.csv。

接著,嘗試以下測試:

第一次填寫表單並送出,確認 CSV 檔案是否建立。

再填寫一筆不同日期的紀錄,確認檔案是否包含兩筆資料。

關閉並重新啟動 Streamlit,再讀取 CSV,確認先前的紀錄是否仍然存在。

檢查欄位名稱是否一致,並確認中文備註是否能正常顯示。

如果這些測試都能通過,就代表系統已經具備基本的資料新增與保存能力。

七、今日實作需要注意的地方

目前的版本會將每次送出的資料直接附加至 CSV,因此同一天可以新增多筆紀錄。如果使用者不小心重複送出同一筆資料,檔案中也可能出現重複紀錄。

這是目前版本仍需要改善的地方。未來可以增加日期重複檢查,或讓使用者修改既有紀錄,而不是每次都新增一筆。

此外,今天的程式尚未將第十二天的資料驗證函式完整整合進來。雖然 Streamlit 的數字輸入元件已經限制部分輸入範圍,但正式系統仍應在資料保存前檢查資料是否符合專案規則。

透過這些限制與問題,也能看出系統開發並不是只要讓程式成功執行就好,還需要逐步考慮資料正確性、重複資料與後續維護等需求。

八、今日成果與學習心得

透過今天的學習,我成功將 Streamlit 表單與 CSV 資料保存功能整合,讓健康習慣追蹤系統不再只是接收輸入並顯示結果,而是能夠將資料寫入檔案,並在之後重新讀取。

今天複習了 Dictionary、Pandas DataFrame、CSV 讀寫與檔案存在檢查,也進一步了解如何將資料輸入、資料整理與資料保存分成不同的程式步驟。

目前系統已經可以完成基本的健康紀錄新增流程,但仍需要繼續改善歷史資料查詢、修改與刪除等功能,才能讓整個系統更完整。

九、下一步學習方向

Day 16 將學習「歷史紀錄查詢:查看過去的健康資料」。

接下來會利用 Pandas 讀取已保存的 CSV,並透過 Streamlit 將歷史健康紀錄呈現在網頁中,讓使用者不只能新增資料,也能查看過去的喝水量、睡眠時間、運動時間與其他生活習慣紀錄,逐步建立完整的健康資料管理功能。


圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言