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