Python CLI จัดการไฟล์ให้ชัวร์ ด้วย Context Manager พร้อม Resilience

สวัสดีครับ เพื่อนๆ โปรแกรมเมอร์

วันนี้ผมมีเรื่องอยากจะมาคุยให้ฟัง เกี่ยวกับการทำ Python CLI ที่ต้องจัดการไฟล์เยอะๆ เนี่ยนะครับ บางทีเราเขียนโค้ดไป เราก็อยากให้มันทำงานแบบชัวร์ๆ ไม่ต้องกลัวไฟล์เสียหาย หรือโปรแกรมค้างกลางคัน ใช่ไหมครับ

ผมเลยอยากจะแนะนำ Context Manager กับแนวคิด Resilience มาใช้กับการจัดการ file-handling ใน python cli ของเรานี่แหละครับ มันช่วยให้โค้ดเราดูสะอาดขึ้น แล้วก็ทำงานได้ทนทานมากๆ เลยนะ

มาดูตัวอย่างกันเลยนะครับ

1. จัดการไฟล์แบบ Context Manager ทั่วไป: ปกติเวลาเราเปิดไฟล์ เราก็จะใช้ open() แบบนี้ใช่ไหมครับ แล้วก็ต้องมา close() เอง ถ้าลืม หรือ โปรแกรมมี error ตรงกลางเนี่ย ไฟล์อาจจะเปิดค้างได้เลยนะ

# โค้ดแบบเก่าๆ ที่อาจมีปัญหา
file = open('data.txt', 'w')
try:
    file.write('Hello World')
finally:
    file.close()

แต่ถ้าใช้ Context Manager มันจะง่ายกว่าเยอะเลยครับ แบบนี้เลยนะ:

# ใช้ Context Manager ให้โค้ดสะอาดขึ้น
with open('data.txt', 'w') as file:
    file.write('Hello World')
# ไม่ต้องเรียก file.close() เองแล้วครับ ระบบจัดการให้

2. เพิ่ม Resilience ให้กับการเขียนไฟล์: ทีนี้ ถ้าเกิดระหว่างที่เราเขียนไฟล์ เกิดมีอะไรผิดพลาดขึ้นมาละครับ เช่น ดิสก์เต็ม หรือไฟดับเนี่ย ข้อมูลเราอาจจะเสียหายได้นะ เราจะทำยังไงดี?

เทคนิคหนึ่งที่ผมชอบใช้ คือการเขียนไปที่ไฟล์ชั่วคราวก่อน temp file นะครับ แล้วค่อย Rename กลับมาทับไฟล์จริง ถ้าทุกอย่างโอเค

import os
import tempfile

def safe_write(filepath, content):
    # สร้างไฟล์ชั่วคราวในโฟลเดอร์เดียวกับไฟล์เป้าหมาย
    fd, temp_path = tempfile.mkstemp(dir=os.path.dirname(filepath))
    try:
        with os.fdopen(fd, 'w') as tmp_file:
            tmp_file.write(content)
        # ถ้าเขียนเสร็จสมบูรณ์ ค่อย rename ไฟล์ชั่วคราวมาทับไฟล์จริง
        os.replace(temp_path, filepath)
        print(f\"เขียนไฟล์ {filepath} สำเร็จแล้วครับ\")
    except Exception as e:
        print(f\"มีปัญหาตอนเขียนไฟล์ {filepath}: {e} ครับ\")
        # ถ้ามีปัญหา ให้ลบไฟล์ชั่วคราวทิ้ง
        os.remove(temp_path)

# ลองใช้งานดูนะครับ
safe_write('important_report.txt', 'รายงานลับสุดยอด\
ยังไม่เสร็จนะ')

เห็นไหมครับ แบบนี้ ถ้าเกิดมีอะไรผิดพลาดระหว่างเขียน ไฟล์ important_report.txt เดิมของเราก็จะยังอยู่ครบ ไม่พังนะครับ

3. รวม Resilience เข้ากับ Context Manager แบบง่ายๆ: เราสามารถสร้าง Context Manager ของเราเอง เพื่อรวมความสามารถนี้ได้นะ มันจะช่วยให้โค้ดเราดูโปรมากๆ เลยครับ

from contextlib import contextmanager
import os
import tempfile

@contextmanager
def resilient_file_writer(filepath):
    fd, temp_path = tempfile.mkstemp(dir=os.path.dirname(filepath))
    try:
        with os.fdopen(fd, 'w') as tmp_file:
            yield tmp_file # ส่ง object ไฟล์ให้ผู้ใช้
        # ถ้าไม่มี exception แปลว่าเขียนสำเร็จ ก็ rename
        os.replace(temp_path, filepath)
        print(f\"เขียนไฟล์ {filepath} สำเร็จด้วย resilient writer ครับ\")
    except Exception as e:
        print(f\"มีปัญหาตอนเขียนไฟล์ {filepath}: {e} ครับ\")
        os.remove(temp_path) # ลบไฟล์ชั่วคราวทิ้งถ้ามีปัญหา
        raise # โยน exception ให้ผู้ใช้จัดการต่อ

# ทีนี้มาลองใช้กันดูนะครับ
# กรณีสำเร็จ
with resilient_file_writer('config.json') as f:
    f.write('{ \"setting\": \"value\" }')

# กรณีมีปัญหา (สมมติ)
try:
    with resilient_file_writer('log.txt') as f:
        f.write('เริ่มทำงาน\
')
        raise ValueError(\"จำลอง error ในการเขียนไฟล์ครับ\") # จำลอง error
        f.write('เสร็จสิ้น') # โค้ดนี้จะไม่ถูกเรียก
except ValueError as e:
    print(f\"ผู้ใช้จับ error ได้: {e} ครับ\")

แบบนี้ก็เป็นการสร้าง CLI tool ของเราให้ resilient แล้วก็จัดการ file-handling ได้ดีขึ้นมากๆ เลยนะครับ ทำให้การ optimization ในเรื่องความเสี่ยงของข้อมูลที่เราเขียนทำได้ดียิ่งขึ้น

เพื่อนๆ ลองเอาเทคนิคนี้ไปปรับใช้กับโปรเจกต์ของตัวเองดูได้เลยนะครับ ผมว่ามันช่วยได้เยอะเลยแหละ

ขอให้สนุกกับการเขียนโค้ดนะครับ!

cii3.net

Read more

ตารางคะแนนบอลโลก: ทุกแต้มมีความหมาย และปาฏิหาริย์ที่สั่นสะเทือนบัลลังก์

ตารางคะแนนบอลโลก: ทุกแต้มมีความหมาย และปาฏิหาริย์ที่สั่นสะเทือนบัลลังก์

เจาะลึกความสำคัญของตารางคะแนนบอลโลก พร้อมเรื่องราวสุดประทับใจของโวซินญา ผู้รักษาประตูเคปเวิร์ดที่สร้างปาฏิหาริย์หยุดสเปนในฟุตบอลโลก 2026.

By ทีมงาน devdog
ประธานเจ้าหน้าที่ฝ่ายกฎหมาย Take-Two ขายหุ้นมูลค่า 950,515 ดอลลาร์: สัญญาณอะไรที่นักลงทุนควรรู้?

ประธานเจ้าหน้าที่ฝ่ายกฎหมาย Take-Two ขายหุ้นมูลค่า 950,515 ดอลลาร์: สัญญาณอะไรที่นักลงทุนควรรู้?

ประธานเจ้าหน้าที่ฝ่ายกฎหมาย Take-Two ขายหุ้นเกือบ $1 ล้าน ท่ามกลางข่าวดี GTA 6 และรายได้คาดการณ์ $8 พันล้าน นักลงทุนควรรู้อะไร?

By ทีมงาน devdog
เตรียมทีมให้พร้อม! เจาะลึก Pokémon Champion Team ในยุค Mobile และ Regulation M-B

เตรียมทีมให้พร้อม! เจาะลึก Pokémon Champion Team ในยุค Mobile และ Regulation M-B

Pokémon Champions เปิดตัวบนมือถือแล้ว พร้อม Regulation M-B ที่นำ Mega Evolution ใหม่ และการเปลี่ยนแปลงครั้งใหญ่ มาดูวิธีจัดทีมโปเกมอนแชมเปี้ยนของคุณ!

By ทีมงาน devdog