0Pricing
AI Agents · บทเรียน

การดำเนินการกับไฟล์อย่างปลอดภัยพร้อมจัดการข้อผิดพลาด

ตรวจสอบการมีอยู่ของไฟล์ สิทธิ์การเข้าถึง และจัดการข้อผิดพลาด IO อย่างเหมาะสม

การดำเนินการกับไฟล์อย่างปลอดภัยพร้อมจัดการข้อผิดพลาด เป็นบทเรียน AI Agents ฟรีบน CoddyKit นี่คือบทเรียนที่ 4 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน AI Agents และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส AI Agents มีบทเรียนทั้งหมด 4 บทเรียน

เหตุผลที่การดำเนินการกับไฟล์อย่างปลอดภัยมีความสำคัญ

การดำเนินการกับไฟล์ในเอเจนต์อาจล้มเหลวได้หลายรูปแบบ เช่น ไม่มีไฟล์อยู่ เอเจนต์ไม่มีสิทธิ์เข้าถึง พาธเป็นไดเรกทอรี หรือพื้นที่ดิสก์หมดระหว่างการเขียน เอเจนต์ที่หยุดทำงานเมื่อเกิดข้อผิดพลาดเกี่ยวกับไฟล์จะทิ้งผลลัพธ์ที่เขียนไว้เพียงบางส่วนและสถานะที่เสียหาย การเขียนโปรแกรมเชิงป้องกันด้วยการตรวจสอบและการจัดการข้อผิดพลาดที่เหมาะสมจะทำให้เอเจนต์ทำงานได้อย่างทนทาน

from pathlib import Path

# Unsafe: crashes with FileNotFoundError
# content = Path('missing.txt').read_text()

# Safe: check first
path = Path('config.json')
if path.exists():
    content = path.read_text(encoding='utf-8')
    print('Loaded config')
else:
    print(f'Config not found at {path.resolve()}')
    content = '{}'  # use default

Path.exists() และ Path.is_file()

ก่อนอ่านไฟล์ โปรดตรวจสอบว่าไฟล์นั้นมีอยู่ และ เป็นไฟล์ปกติจริง (ไม่ใช่ไดเรกทอรี ลิงก์สัญลักษณ์ไปยังไดเรกทอรี หรือไฟล์ชนิดพิเศษ) Path.exists() จะคืนค่าเป็นจริงสำหรับออบเจ็กต์ใด ๆ ในระบบไฟล์ ส่วน Path.is_file() จะคืนค่าเป็นจริงเฉพาะไฟล์ปกติเท่านั้น

from pathlib import Path

path = Path('data/report.csv')

# Chain of checks
if not path.exists():
    print(f'Not found: {path}')
elif not path.is_file():
    print(f'Not a regular file: {path} (is_dir={path.is_dir()})')
elif path.stat().st_size == 0:
    print(f'File is empty: {path}')
else:
    # Safe to read
    import csv
    with open(path, 'r', encoding='utf-8', newline='') as f:
        reader = csv.DictReader(f)
        rows = list(reader)
    print(f'Read {len(rows)} rows')

os.access() — การตรวจสอบสิทธิ์

os.access(path, mode) ตรวจสอบว่ากระบวนการปัจจุบันมีสิทธิ์ที่ระบุไว้สำหรับไฟล์หรือไม่ ใช้ os.R_OK สำหรับการอ่าน os.W_OK สำหรับการเขียน และ os.X_OK สำหรับการเรียกใช้งาน วิธีนี้มีประโยชน์ก่อนดำเนินการที่ต้องใช้สิทธิ์เฉพาะ

import os
from pathlib import Path

def check_file_access(path):
    p = Path(path)

    checks = {
        'exists': p.exists(),
        'is_file': p.is_file(),
        'readable': os.access(p, os.R_OK),
        'writable': os.access(p, os.W_OK),
    }

    for check, result in checks.items():
        status = 'OK' if result else 'FAIL'
        print(f'  {check}: {status}')

    return all(checks.values())

if check_file_access('data/input.json'):
    print('File is accessible')
else:
    print('Access problem — check path and permissions')

การดักจับ FileNotFoundError

FileNotFoundError (คลาสย่อยของ OSError) จะถูกแจ้งขึ้นเมื่อคุณพยายามเปิดไฟล์ที่ไม่มีอยู่ โปรดดักจับข้อผิดพลาดนี้โดยเฉพาะ และแสดงข้อความผิดพลาดที่เป็นประโยชน์ซึ่งระบุพาธที่คาดไว้ เพื่อให้ผู้ใช้หรือผู้ดูแลระบบทราบอย่างชัดเจนว่าสิ่งใดหายไป

import json
from pathlib import Path

def load_agent_config(config_path='agent_config.json'):
    path = Path(config_path)
    try:
        with open(path, 'r', encoding='utf-8') as f:
            return json.load(f)
    except FileNotFoundError:
        print(f'Config file not found: {path.resolve()}')
        print('Create agent_config.json with your settings')
        print('Example: {"model": "gpt-4o", "max_retries": 3}')
        return {}  # return empty config as default
    except json.JSONDecodeError as e:
        print(f'Invalid JSON in {path}: {e}')
        return {}

# --- demo ---
config = load_agent_config('does_not_exist_config.json')
print(f'Config used: {config}')

การดักจับ PermissionError

PermissionError จะถูกแจ้งขึ้นเมื่อกระบวนการไม่มีสิทธิ์อ่านหรือเขียนไฟล์ เหตุการณ์นี้อาจเกิดกับไฟล์ระบบ ไฟล์ที่ผู้ใช้อื่นเป็นเจ้าของ หรือไฟล์ที่มีการกำหนดสิทธิ์อย่างเข้มงวด โปรดดักจับข้อผิดพลาดนี้แยกจาก FileNotFoundError เสมอ เพราะข้อผิดพลาดทั้งสองต้องใช้การตอบสนองที่แตกต่างกัน

from pathlib import Path

def read_file_safely(path):
    try:
        return Path(path).read_text(encoding='utf-8')
    except FileNotFoundError:
        print(f'File not found: {path}')
        return None
    except PermissionError:
        import os
        print(f'Permission denied: {path}')
        print(f'File permissions: {oct(Path(path).stat().st_mode)}')
        print(f'Current user: {os.getlogin()}')
        print('Try: chmod +r ' + str(path))
        return None
    except IsADirectoryError:
        print(f'Path is a directory, not a file: {path}')
        return None

# --- demo ---
import os
print(read_file_safely('does_not_exist.txt'))

os.makedirs('a_directory', exist_ok=True)
print(read_file_safely('a_directory'))

การดักจับ IsADirectoryError

IsADirectoryError จะถูกแจ้งขึ้นเมื่อคุณพยายามเปิดไดเรกทอรีเสมือนเป็นไฟล์ เหตุการณ์นี้อาจเกิดขึ้นเมื่อเอเจนต์สร้างพาธไม่ถูกต้อง เช่น ต่อชื่อไฟล์ที่มีอยู่เป็นไดเรกทอรีอยู่แล้ว โปรดดักจับข้อผิดพลาดนี้เสมอเพื่อแสดงผลลัพธ์ข้อผิดพลาดที่มีความหมาย

from pathlib import Path

def safe_write(output_path, content):
    path = Path(output_path)

    # Check the path is not an existing directory
    if path.is_dir():
        raise IsADirectoryError(
            f'Cannot write file: {path} is a directory. '
            f'Use a filename like {path}/output.txt instead.'
        )

    # Ensure parent directory exists
    path.parent.mkdir(parents=True, exist_ok=True)

    try:
        path.write_text(content, encoding='utf-8')
        print(f'Written: {path} ({len(content)} chars)')
    except IsADirectoryError as e:
        print(f'Path error: {e}')
    except PermissionError:
        print(f'Cannot write to {path} — permission denied')

# --- demo ---
import os
safe_write('demo_output/report.txt', 'Agent finished the task.')

os.makedirs('already_a_dir', exist_ok=True)
try:
    safe_write('already_a_dir', 'this will fail')
except IsADirectoryError as e:
    print(f'Rejected: {e}')

การเขียนแบบอะตอมิกด้วยไฟล์ชั่วคราว

การเขียนลงไฟล์โดยตรงมีความเสี่ยง หากเอเจนต์หยุดทำงานระหว่างการเขียน ไฟล์จะถูกเขียนไว้เพียงบางส่วนและเสียหาย วิธีแก้คือ การเขียนแบบอะตอมิก โดยเขียนลงไฟล์ชั่วคราวก่อน แล้วจึงเปลี่ยนชื่อเป็นพาธปลายทาง การเปลี่ยนชื่อเป็นการดำเนินการแบบอะตอมิกบนระบบ POSIX ดังนั้นไฟล์ปลายทางจะเป็นเวอร์ชันเก่าหรือเวอร์ชันใหม่อย่างใดอย่างหนึ่งเสมอ และจะไม่มีวันเป็นไฟล์ที่เขียนไว้เพียงบางส่วน

import tempfile
import os
import json
from pathlib import Path

def atomic_write_json(file_path, data):
    path = Path(file_path)
    path.parent.mkdir(parents=True, exist_ok=True)

    # Write to temp file in same directory
    tmp_fd, tmp_path = tempfile.mkstemp(
        dir=path.parent,
        prefix='.tmp_',
        suffix='.json'
    )
    try:
        with os.fdopen(tmp_fd, 'w', encoding='utf-8') as f:
            json.dump(data, f, indent=2, ensure_ascii=False)
        # Atomic rename: replaces final file in one operation
        os.replace(tmp_path, path)
        print(f'Atomically wrote: {path}')
    except Exception as e:
        os.unlink(tmp_path)  # clean up temp file on error
        raise

# --- demo ---
atomic_write_json('demo_state/state.json', {'step': 3, 'status': 'running'})
print('File contents:', Path('demo_state/state.json').read_text(encoding='utf-8'))

การล็อกไฟล์สำหรับเอเจนต์ที่ทำงานพร้อมกัน

เมื่ออินสแตนซ์ของเอเจนต์หลายตัวทำงานพร้อมกันและเขียนลงไฟล์เดียวกัน เงื่อนไขการแข่งขันอาจทำให้ข้อมูลเสียหายได้ ใช้ การล็อกไฟล์ ด้วยโมดูล fcntl (Linux/macOS) หรือไลบรารีล็อกไฟล์ที่รองรับหลายแพลตฟอร์ม เพื่อป้องกันการเขียนพร้อมกัน

from filelock import FileLock, Timeout
import json
from pathlib import Path

COUNTER_FILE = Path('shared_counter.json')
LOCK_FILE = Path('shared_counter.json.lock')

def increment_counter():
    lock = FileLock(str(LOCK_FILE), timeout=10)
    try:
        with lock:
            # Only one process can be here at a time
            if COUNTER_FILE.exists():
                data = json.loads(COUNTER_FILE.read_text())
            else:
                data = {'count': 0}

            data['count'] += 1
            COUNTER_FILE.write_text(
                json.dumps(data, indent=2)
            )
            return data['count']
    except Timeout:
        print('Could not acquire lock within 10 seconds')
        return None

การลบอย่างปลอดภัยโดยตรวจสอบการมีอยู่

การลบไฟล์ที่ไม่มีอยู่จะทำให้เกิด FileNotFoundError การลบไดเรกทอรีด้วย Path.unlink() จะทำให้เกิด IsADirectoryError ใช้ Path.unlink(missing_ok=True) (Python 3.8 ขึ้นไป) หรือตรวจสอบการมีอยู่ก่อนเพื่อลบอย่างปลอดภัย

from pathlib import Path
import shutil

# Safe file deletion (Python 3.8+)
Path('temp_output.json').unlink(missing_ok=True)

# Safe directory deletion
def safe_remove(path):
    p = Path(path)
    if not p.exists():
        print(f'Already gone: {p}')
        return
    if p.is_file():
        p.unlink()
        print(f'Deleted file: {p}')
    elif p.is_dir():
        shutil.rmtree(p)
        print(f'Deleted directory: {p}')
    else:
        print(f'Unknown file type: {p}')

# Clean up temporary workspace
safe_remove('/tmp/agent_workspace/run_001')

การตรวจสอบพื้นที่ดิสก์ก่อนเขียน

เอเจนต์ที่เขียนไฟล์ขนาดใหญ่ เช่น ผลลัพธ์จาก AI ชุดข้อมูล และบันทึกการทำงาน ควรตรวจสอบพื้นที่ดิสก์ที่ใช้ได้ก่อน shutil.disk_usage(path) จะคืนค่าจำนวนไบต์ทั้งหมด ไบต์ที่ใช้ไป และไบต์ที่ว่างอยู่ โปรดตรวจสอบว่าพื้นที่ว่างมากกว่าขนาดผลลัพธ์ที่คาดไว้ก่อนเริ่มการเขียนที่ใช้เวลานาน

import shutil
from pathlib import Path

def check_disk_space(output_dir, required_bytes):
    path = Path(output_dir)
    path.mkdir(parents=True, exist_ok=True)

    usage = shutil.disk_usage(path)
    free_gb = usage.free / (1024 ** 3)
    required_gb = required_bytes / (1024 ** 3)

    print(f'Disk free: {free_gb:.2f} GB')
    print(f'Required:  {required_gb:.2f} GB')

    if usage.free < required_bytes * 1.1:  # 10% safety margin
        raise IOError(
            f'Insufficient disk space: '
            f'{free_gb:.2f} GB free, '
            f'{required_gb:.2f} GB required'
        )
    return True

# Before writing a 500 MB dataset
check_disk_space('/tmp/output', 500 * 1024 * 1024)

สำรองข้อมูลก่อนเขียนทับ

เมื่อเอเจนต์อัปเดตไฟล์ที่มีอยู่แล้ว ขอแนะนำให้เก็บข้อมูลสำรองของเวอร์ชันก่อนหน้าไว้ วิธีนี้ช่วยให้ย้อนกลับได้หากเนื้อหาใหม่ไม่ถูกต้อง ใช้ชื่อไฟล์สำรองที่มีการประทับเวลา และจำกัดจำนวนไฟล์สำรองเพื่อไม่ให้พื้นที่ดิสก์เต็ม

import shutil
import datetime
from pathlib import Path

def write_with_backup(file_path, content, max_backups=5):
    path = Path(file_path)
    backup_dir = path.parent / '.backups'
    backup_dir.mkdir(exist_ok=True)

    # Backup existing file
    if path.exists():
        timestamp = datetime.datetime.now().strftime('%Y%m%d_%H%M%S')
        backup = backup_dir / f'{path.name}.{timestamp}'
        shutil.copy2(path, backup)
        print(f'Backed up to: {backup}')

    # Write new content
    path.write_text(content, encoding='utf-8')

    # Prune old backups
    backups = sorted(backup_dir.glob(f'{path.name}.*'))
    for old in backups[:-max_backups]:
        old.unlink()
        print(f'Pruned old backup: {old.name}')

# --- demo ---
write_with_backup('demo_notes.txt', 'version 1')
write_with_backup('demo_notes.txt', 'version 2')
print('Backups:', [p.name for p in sorted(Path('.backups').glob('demo_notes.txt.*'))])

แบบทดสอบสั้น ๆ: การเขียนแบบอะตอมิก

ทดสอบความเข้าใจเกี่ยวกับรูปแบบการเขียนไฟล์อย่างปลอดภัย

สรุปการดำเนินการกับไฟล์อย่างปลอดภัย

ขณะนี้เอเจนต์ของคุณสามารถจัดการไฟล์อย่างระมัดระวังได้แล้ว:

  • ตรวจสอบก่อนเข้าถึง: Path.exists() + Path.is_file() + os.access(path, os.R_OK)
  • ดักจับ FileNotFoundError, PermissionError และ IsADirectoryError พร้อมแสดงข้อความที่ชัดเจน
  • ใช้ การเขียนแบบอะตอมิก (ไฟล์ชั่วคราว + os.replace) เพื่อป้องกันไฟล์ที่เขียนไม่ครบหรือเสียหายเมื่อโปรแกรมหยุดทำงาน
  • ใช้ การล็อกไฟล์ (ไลบรารีล็อกไฟล์) เมื่อเอเจนต์หลายตัวเขียนลงไฟล์เดียวกัน
  • ใช้ missing_ok=True เพื่อลบอย่างปลอดภัยโดยไม่ทำให้เกิด FileNotFoundError
  • ตรวจสอบ พื้นที่ดิสก์ ก่อนการเขียนขนาดใหญ่ และเก็บ ข้อมูลสำรอง ก่อนเขียนทับไฟล์สำคัญ

คำถามที่พบบ่อย

บทเรียน “การดำเนินการกับไฟล์อย่างปลอดภัยพร้อมจัดการข้อผิดพลาด” ฟรีหรือไม่

ใช่ — ข้อความเต็มของ “การดำเนินการกับไฟล์อย่างปลอดภัยพร้อมจัดการข้อผิดพลาด” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส AI Agents ให้อัปเกรดเป็น CoddyKit PRO คอร์ส AI Agents มีบทเรียนทั้งหมด 4 บทเรียน

คุณจะเรียนรู้อะไรในบทเรียน “การดำเนินการกับไฟล์อย่างปลอดภัยพร้อมจัดการข้อผิดพลาด”

ตรวจสอบการมีอยู่ของไฟล์ สิทธิ์การเข้าถึง และจัดการข้อผิดพลาด IO อย่างเหมาะสม คุณปฏิบัติ AI Agents ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน

คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน AI Agents หรือไม่

ไม่จำเป็นต้องมีประสบการณ์มาก่อน AI Agents บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 4 จากทั้งหมด 4 บทเรียน

บทเรียน “การดำเนินการกับไฟล์อย่างปลอดภัยพร้อมจัดการข้อผิดพลาด” ใช้เวลานานแค่ไหน

บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย

ฉันเขียนและรันโค้ดในบทเรียน AI Agents นี้ได้ไหม

ได้ บทเรียน AI Agents ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ

บทเรียนทั้งหมดในหลักสูตรนี้

  1. การอ่านและเขียนไฟล์ในบริบทของตัวแทน
  2. การไล่สำรวจไดเรกทอรีและค้นหาไฟล์
  3. การจัดการรูปแบบไฟล์: CSV, JSON และ TXT
  4. การดำเนินการกับไฟล์อย่างปลอดภัยพร้อมจัดการข้อผิดพลาด
← กลับไปที่ AI Agents