Säkra filoperationer med felhantering
Kontrollera att filer finns och att du har behörighet samt hantera IO-fel på ett robust sätt.
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 defaultPath.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 NoneSä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
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
- Läsa och skriva filer i agentkontext
- Katalogtraversering och filsökning
- Filformat: CSV, JSON och TXT
- Säkra filoperationer med felhantering