AI-agenter · Lektion

Säkra filoperationer med felhantering

Kontrollera att filer finns och att du har behörighet samt hantera IO-fel på ett robust sätt.

Lektion 4 av 413 steg

Säkra filoperationer med felhantering är en gratis lektion i AI-agenter på CoddyKit. Detta är lektion 4 av 4. Ni kan läsa hela lektionen gratis nedan och sedan öva praktiskt i webbläsaren med en inbyggd kodredigerare och en AI-handledare som är tillgänglig dygnet runt. Den ingår i lärvägen för AI-agenter, och Era framsteg synkroniseras mellan webben och CoddyKit-appen. Kursen i AI-agenter innehåller totalt 4 lektioner.

Varför säkra filoperationer är viktiga

Filoperationer i agenter kan misslyckas på många sätt: filen finns inte, agenten saknar behörighet, sökvägen är en katalog eller diskutrymmet tar slut mitt under skrivningen. En agent som kraschar på grund av ett filfel lämnar efter sig ofullständig utdata och ett korrupt tillstånd. Defensiv programmering med korrekta kontroller och felhantering gör agenter motståndskraftiga.

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() och Path.is_file()

Innan Ni läser en fil bör Ni kontrollera att den finns och verkligen är en vanlig fil (inte en katalog, en symbolisk länk till en katalog eller en specialfil). Path.exists() returnerar True för alla objekt i filsystemet, medan Path.is_file() endast returnerar True för vanliga filer.

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() — Kontroll av behörigheter

os.access(path, mode) kontrollerar om den aktuella processen har den angivna behörigheten för en fil. Använd os.R_OK för läsning, os.W_OK för skrivning och os.X_OK för körning. Detta är användbart innan Ni försöker utföra åtgärder som kräver specifika behörigheter.

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')

Fånga FileNotFoundError

FileNotFoundError (en underklass till OSError) kastas när Ni försöker öppna en fil som inte finns. Fånga undantaget uttryckligen och visa ett användbart felmeddelande som innehåller den förväntade sökvägen, så att användaren eller operatören exakt vet vad som saknas.

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}')

Fånga PermissionError

PermissionError kastas när processen saknar behörighet att läsa eller skriva en fil. Det kan hända med systemfiler, filer som ägs av en annan användare eller filer med begränsande behörigheter. Fånga alltid detta separat från FileNotFoundError — de kräver olika åtgärder.

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'))

Fånga IsADirectoryError

IsADirectoryError kastas när Ni försöker öppna en katalog som om den vore en fil. Det kan hända när en agent konstruerar en sökväg felaktigt — till exempel när ett filnamn läggs till trots att det redan finns en katalog med det namnet. Fånga alltid undantaget för att kunna ge en meningsfull felutskrift.

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}')

Atomiska skrivningar med tempfile

Det är riskabelt att skriva direkt till en fil — om agenten kraschar mitt under skrivningen blir filen delvis skriven och skadad. Lösningen är en atomisk skrivning: skriv först till en temporär fil och byt sedan namn på den till den slutliga sökvägen. Namnbyte är atomiskt på POSIX-system — den slutliga filen är antingen den gamla versionen eller den nya, aldrig en ofullständig version.

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'))

Fillåsning för samtidiga agenter

När flera agentinstanser körs parallellt och skriver till samma fil kan race conditions skada data. Använd fillåsning med modulen fcntl (Linux/macOS) eller det plattformsoberoende biblioteket filelock för att förhindra samtidiga skrivningar.

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

Säker borttagning med existenskontroller

Om Ni tar bort en fil som inte finns kastas FileNotFoundError. Om Ni tar bort en katalog med Path.unlink() kastas IsADirectoryError. Använd Path.unlink(missing_ok=True) (Python 3.8+) eller kontrollera att filen finns först för säker borttagning.

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')

Kontrollera diskutrymmet före skrivning

Agenter som skriver stora filer (AI-utdata, datauppsättningar och loggar) bör kontrollera det tillgängliga diskutrymmet först. shutil.disk_usage(path) returnerar totalt, använt och ledigt utrymme i byte. Kontrollera att det lediga utrymmet överstiger den förväntade storleken på utdata innan Ni påbörjar en lång skrivoperation.

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)

Säkerhetskopiera före överskrivning

När en agent uppdaterar en befintlig fil är det klokt att spara en säkerhetskopia av den tidigare versionen. Då kan Ni återställa den om det nya innehållet är felaktigt. Använd ett tidsstämplat filnamn för säkerhetskopian och begränsa antalet säkerhetskopior så att diskutrymmet inte tar slut.

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.*'))])

Snabbtest: atomiska skrivningar

Testa Er förståelse av säkra mönster för filskrivning.

Sammanfattning: säkra filoperationer

Era agenter kan nu hantera filer på ett defensivt sätt:

  • Kontrollera före åtkomst: Path.exists() + Path.is_file() + os.access(path, os.R_OK)
  • Fånga FileNotFoundError, PermissionError och IsADirectoryError med tydliga meddelanden
  • Använd atomiska skrivningar (tempfile + os.replace) för att förhindra ofullständiga eller skadade filer vid krascher
  • Använd fillåsning (biblioteket filelock) när flera agenter skriver till samma fil
  • Använd missing_ok=True för säker borttagning utan FileNotFoundError
  • Kontrollera diskutrymmet före stora skrivningar och behåll säkerhetskopior innan viktiga filer skrivs över
Gratis att börja

Lär dig AI-agenter med en AI-lärare – gratis

Skriv och kör riktig kod i webbläsaren, få omedelbar hjälp av en AI-lärare dygnet runt och fortsätt där du slutade – på webben eller i appen.

Kurser
60
Lektioner
239

Vanliga frågor

Är lektionen ”Säkra filoperationer med felhantering” gratis?

Ja – hela texten till ”Säkra filoperationer med felhantering” kan läsas gratis här på webben. Om Ni vill öva interaktivt med en inbyggd kodredigerare och en AI-handledare som är tillgänglig dygnet runt och låsa upp resten av kursen i AI-agenter, kan Ni uppgradera till CoddyKit PRO. Kursen i AI-agenter innehåller totalt 4 lektioner.

Vad lär jag mig i ”Säkra filoperationer med felhantering”?

Kontrollera att filer finns och att du har behörighet samt hantera IO-fel på ett robust sätt. Ni övar på AI-agenter med praktisk kod som körs direkt i webbläsaren, medan en AI-handledare som är tillgänglig dygnet runt svarar på Era frågor under lektionen.

Behöver jag någon erfarenhet för att börja lära mig AI-agenter?

Du behöver inga förkunskaper. Utbildningen i AI-agenter på CoddyKit är upplagd för allt från nybörjare till avancerade elever, så att du kan börja här eller från början och gå fram i din egen takt. Detta är lektion 4 av 4.

Hur lång tid tar lektionen ”Säkra filoperationer med felhantering”?

De flesta CoddyKit-lektioner tar cirka 5–10 minuter. Varje lektion är kort och interaktiv, så att du gör stadiga framsteg och kan fortsätta precis där du slutade – på webben eller i appen.

Kan jag skriva och köra kod i den här AI-agenter-lektionen?

Ja. Varje AI-agenter-lektion innehåller en inbyggd kodredigerare, så att du kan skriva och köra riktig kod direkt i webbläsaren och få omedelbar AI-feedback – utan lokal installation.

Alla lektioner i den här kursen

  1. Läsa och skriva filer i agentkontext
  2. Katalogtraversering och filsökning
  3. Filformat: CSV, JSON och TXT
  4. Säkra filoperationer med felhantering
← Tillbaka till AI-agenter