Operasi Fail Selamat dengan Pengendalian Ralat
Menyemak kewujudan fail dan keizinan serta mengendalikan ralat IO dengan baik.
Operasi Fail Selamat dengan Pengendalian Ralat ialah pelajaran Ejen AI percuma di CoddyKit. Ini ialah pelajaran 4 daripada 4. Anda boleh membaca keseluruhan pelajaran di bawah secara percuma — kemudian berlatih secara praktikal dalam pelayar menggunakan penyunting kod terbina dalam dan tutor kecerdasan buatan 24/7. Pelajaran ini merupakan sebahagian daripada laluan pembelajaran Ejen AI, dan kemajuan anda disegerakkan merentas web serta aplikasi CoddyKit. Kursus Ejen AI merangkumi sejumlah 4 pelajaran.
Mengapa Operasi Fail yang Selamat Penting
Operasi fail dalam ejen boleh gagal dalam banyak keadaan: fail tidak wujud, ejen tidak mempunyai kebenaran, laluan ialah direktori atau ruang cakera habis semasa penulisan. Ejen yang ranap akibat ralat fail akan meninggalkan keluaran separa dan keadaan yang rosak. Pengaturcaraan defensif dengan pemeriksaan serta pengendalian ralat yang betul menjadikan ejen lebih teguh.
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() dan Path.is_file()
Sebelum membaca fail, semak bahawa fail itu wujud dan benar-benar merupakan fail biasa (bukan direktori, pautan simbolik ke direktori atau fail khas). Path.exists() mengembalikan True untuk sebarang objek sistem fail; Path.is_file() mengembalikan True hanya untuk fail biasa.
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() — Menyemak Kebenaran
os.access(path, mode) menyemak sama ada proses semasa mempunyai kebenaran yang ditentukan pada sesuatu fail. Gunakan os.R_OK untuk membaca, os.W_OK untuk menulis dan os.X_OK untuk melaksanakan. Ini berguna sebelum mencuba operasi yang memerlukan kebenaran tertentu.
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')Menangkap FileNotFoundError
FileNotFoundError (subkelas OSError) dicetuskan apabila anda cuba membuka fail yang tidak wujud. Tangkapnya secara khusus dan berikan mesej ralat yang berguna, termasuk laluan yang dijangka, supaya pengguna atau pengendali mengetahui perkara yang tiada dengan tepat.
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}')
Menangkap PermissionError
PermissionError dicetuskan apabila proses tidak mempunyai kebenaran untuk membaca atau menulis fail. Keadaan ini boleh berlaku pada fail sistem, fail milik pengguna lain atau fail dengan kebenaran yang ketat. Sentiasa tangkapnya secara berasingan daripada FileNotFoundError — kedua-duanya memerlukan tindakan yang berbeza.
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'))
Menangkap IsADirectoryError
IsADirectoryError dicetuskan apabila anda cuba membuka direktori seolah-olah ia sebuah fail. Keadaan ini boleh berlaku apabila ejen membina laluan secara salah — contohnya, menambahkan nama fail yang sebenarnya sudah wujud sebagai direktori. Sentiasa tangkapnya supaya output ralat yang diberikan bermakna.
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}')
Penulisan Atom dengan Fail Sementara
Menulis terus ke dalam fail adalah berbahaya — jika ejen ranap ketika proses penulisan berlangsung, fail itu akan menjadi separa ditulis dan rosak. Penyelesaiannya ialah penulisan atom: tulis dahulu ke dalam fail sementara, kemudian namakannya semula kepada laluan akhir. Penamaan semula adalah atom pada sistem POSIX — fail akhir sama ada versi lama atau versi baharu, tidak pernah versi separa.
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'))
Penguncian Fail untuk Ejen Serentak
Apabila beberapa tika ejen berjalan secara selari dan menulis ke fail yang sama, keadaan perlumbaan boleh merosakkan data. Gunakan penguncian fail dengan modul fcntl (Linux/macOS) atau pustaka filelock merentas platform untuk menghalang penulisan serentak.
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 NonePemadaman Selamat dengan Semakan Kewujudan
Memadam fail yang tidak wujud akan mencetuskan FileNotFoundError. Memadam direktori dengan Path.unlink() akan mencetuskan IsADirectoryError. Gunakan Path.unlink(missing_ok=True) (Python 3.8+) atau semak kewujudan terlebih dahulu untuk pemadaman yang selamat.
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')Semakan Ruang Cakera Sebelum Menulis
Ejen yang menulis fail besar (output AI, set data, log) hendaklah menyemak ruang cakera yang tersedia terlebih dahulu. shutil.disk_usage(path) mengembalikan bait keseluruhan, digunakan dan bebas. Pastikan ruang bebas melebihi saiz output yang dijangka sebelum memulakan operasi penulisan yang panjang.
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)Sandaran Sebelum Menulis Ganti
Apabila ejen mengemas kini fail sedia ada, sebaik-baiknya simpan sandaran versi sebelumnya. Dengan cara ini, anda boleh membuat pemulihan jika kandungan baharu tidak betul. Gunakan nama fail sandaran bertanda masa dan hadkan bilangan sandaran supaya ruang cakera tidak penuh.
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.*'))])
Semakan Pantas: Penulisan Atom
Uji pemahaman anda tentang corak penulisan fail yang selamat.
Ringkasan Operasi Fail Selamat
Ejen anda kini boleh mengendalikan fail secara defensif:
- Semak sebelum mengakses:
Path.exists()+Path.is_file()+os.access(path, os.R_OK) - Tangkap FileNotFoundError, PermissionError dan IsADirectoryError dengan mesej yang jelas
- Gunakan penulisan atom (fail sementara + os.replace) untuk menghalang fail separa atau rosak apabila berlaku ranap
- Gunakan penguncian fail (pustaka filelock) apabila beberapa ejen menulis ke fail yang sama
- Gunakan missing_ok=True untuk pemadaman selamat tanpa FileNotFoundError
- Semak ruang cakera sebelum penulisan besar; simpan sandaran sebelum menulis ganti fail penting
Pelajari Ejen AI dengan tutor kecerdasan buatan — percuma
Tulis dan jalankan kod sebenar dalam pelayar anda, dapatkan bantuan segera daripada tutor kecerdasan buatan yang tersedia 24/7, dan sambung semula dari tempat anda berhenti di web atau dalam aplikasi.
- Kursus
- 60
- Pelajaran
- 239
Soalan Lazim
Adakah pelajaran “Operasi Fail Selamat dengan Pengendalian Ralat” percuma?
Ya — teks penuh “Operasi Fail Selamat dengan Pengendalian Ralat” boleh dibaca secara percuma di web ini. Untuk berlatih secara interaktif menggunakan penyunting kod terbina dalam dan tutor kecerdasan buatan 24/7, serta membuka kunci baki kursus Ejen AI, tingkat taraf kepada CoddyKit PRO. Kursus Ejen AI merangkumi sejumlah 4 pelajaran.
Apakah yang akan saya pelajari dalam “Operasi Fail Selamat dengan Pengendalian Ralat”?
Menyemak kewujudan fail dan keizinan serta mengendalikan ralat IO dengan baik. Anda berlatih Ejen AI menggunakan kod praktikal yang dijalankan terus dalam pelayar, manakala tutor kecerdasan buatan 24/7 menjawab soalan anda semasa anda mengikuti pelajaran.
Adakah saya memerlukan pengalaman untuk memulakan Ejen AI?
Tiada pengalaman terdahulu diperlukan. Pembelajaran Ejen AI di CoddyKit disusun untuk pelajar daripada peringkat pemula hingga lanjutan, jadi anda boleh bermula di sini atau dari awal dan belajar mengikut kadar anda sendiri. Ini ialah pelajaran 4 daripada 4.
Berapa lamakah pelajaran “Operasi Fail Selamat dengan Pengendalian Ralat” diambil?
Kebanyakan pelajaran CoddyKit mengambil masa kira-kira 5–10 minit. Setiap pelajaran ringkas dan interaktif, jadi anda boleh membuat kemajuan secara berterusan dan menyambung tepat dari tempat anda berhenti di web atau aplikasi.
Bolehkah saya menulis dan menjalankan kod dalam pelajaran Ejen AI ini?
Ya. Setiap pelajaran Ejen AI menyertakan penyunting kod terbina dalam, jadi anda boleh menulis dan menjalankan kod sebenar terus dalam pelayar serta menerima maklum balas kecerdasan buatan serta-merta — tanpa memerlukan persediaan setempat.
Semua pelajaran dalam kursus ini
- Membaca dan Menulis Fail dalam Konteks Ejen
- Penjelajahan Direktori dan Penemuan Fail
- Pengendalian Format Fail: CSV, JSON dan TXT
- Operasi Fail Selamat dengan Pengendalian Ralat