0Pricing
AI Agents · 강의

파일 형식 처리: CSV, JSON, TXT

csv 모듈, json.load/dump, 에이전트 도구를 위한 안전한 텍스트 인코딩을 다룹니다.

파일 형식 처리: CSV, JSON, TXT은(는) CoddyKit의 무료 AI Agents 강의입니다. 이것은 4개 중 3번째 강의입니다. 아래에서 전체 강의를 무료로 읽을 수 있으며, 내장 코드 에디터와 24/7 AI 튜터와 함께 브라우저에서 직접 실습할 수 있습니다. 이 강의는 AI Agents 학습 경로의 일부이며, 진행 상황이 웹과 CoddyKit 앱에 동기화됩니다. AI Agents 강의에는 총 4개의 강의가 포함되어 있습니다.

에이전트가 가장 많이 사용하는 세 가지 파일 형식

에이전트는 표 형식 데이터에 CSV, 구조화된 객체에 JSON, 로그·프롬프트·보고서에 일반 텍스트라는 세 가지 파일 형식을 끊임없이 읽고 씁니다. 각 형식에는 서로 다른 파싱 요구 사항, 예외 상황 및 모범 사례가 있습니다. Python은 이 세 형식을 모두 훌륭하게 기본 지원합니다.

import csv
import json
from pathlib import Path

# Detect format from extension
def read_data_file(file_path):
    path = Path(file_path)
    if path.suffix == '.csv':
        return read_csv(path)
    elif path.suffix == '.json':
        return read_json(path)
    elif path.suffix == '.txt':
        return path.read_text(encoding='utf-8')
    else:
        raise ValueError(f'Unsupported format: {path.suffix}')

csv.reader — 기본 CSV 파싱

csv.reader는 CSV 파일을 한 행씩 파싱하여 각 행을 문자열 목록으로 반환합니다. 따옴표로 묶인 필드, 필드 안에 포함된 쉼표, 따옴표로 묶인 값 안의 줄바꿈을 올바르게 처리합니다. 이는 쉼표로 직접 나누는 방식과 달리 예외적인 형식에서 문제가 발생하지 않습니다.

import csv

with open('sales.csv', 'w', newline='') as f:
    f.write('product,qty,price\nWidget,3,9.99\nGadget,1,19.99\n')

with open('sales.csv', 'r', encoding='utf-8', newline='') as f:
    reader = csv.reader(f)
    header = next(reader)
    print('Columns:', header)

    for row in reader:
        product = row[0]
        quantity = int(row[1])
        price = float(row[2])
        print(f'{product}: {quantity} units at ${price}')

csv.DictReader — 행을 딕셔너리로 읽기

csv.DictReader는 각 행을 열 머리글을 키로 사용하는 OrderedDict(또는 Python 3.8 이상에서는 일반 딕셔너리)로 읽습니다. 위치 기반 인덱싱보다 훨씬 다루기 쉽기 때문에 열의 순서가 바뀌어도 코드의 가독성을 유지할 수 있습니다.

import csv

with open('employees.csv', 'w', newline='') as f:
    f.write('name,department,salary\nAlice,Eng,95000\nBob,Sales,70000\n')

with open('employees.csv', 'r', encoding='utf-8', newline='') as f:
    reader = csv.DictReader(f)
    print('Fields:', reader.fieldnames)

    total_salary = 0
    for row in reader:
        name = row['name']
        department = row['department']
        salary = float(row['salary'])
        total_salary += salary
        print(f'{name} ({department}): ${salary:,.2f}')

    print(f'Total payroll: ${total_salary:,.2f}')

csv.writer 및 DictWriter — CSV 쓰기

행을 목록으로 쓰려면 csv.writer를 사용하고, 딕셔너리로 쓰려면 csv.DictWriter를 사용하십시오. 파일을 열 때는 항상 newline=''을 전달하십시오. csv 모듈이 줄 끝을 직접 처리하여 Windows에서 줄바꿈이 두 번 생기는 것을 방지합니다.

import csv

results = [
    {'task_id': 'T001', 'status': 'completed', 'duration_s': 12.5},
    {'task_id': 'T002', 'status': 'failed', 'duration_s': 3.1},
    {'task_id': 'T003', 'status': 'completed', 'duration_s': 45.8},
]

fieldnames = ['task_id', 'status', 'duration_s']

with open('task_results.csv', 'w', newline='', encoding='utf-8') as f:
    writer = csv.DictWriter(f, fieldnames=fieldnames)
    writer.writeheader()  # write column names
    writer.writerows(results)

print('Wrote task_results.csv')

json.load() 및 json.dump() — 파일 입출력

JSON 파일을 파싱하려면 json.load(file)를 사용하고, 파일에 쓰려면 json.dump(obj, file)를 사용하십시오. 이 함수들은 파일 객체와 함께 작동합니다. 문자열에는 json.loads(string)와 json.dumps(obj)를 사용하십시오. 읽기 쉬운 출력을 위해 항상 indent=2를 사용합니다.

import json

with open('config.json', 'w', encoding='utf-8') as f:
    json.dump({'api_url': 'https://api.example.com', 'timeout': 15}, f)

with open('config.json', 'r', encoding='utf-8') as f:
    config = json.load(f)

print('API URL:', config.get('api_url'))
print('Timeout:', config.get('timeout', 30))

output_data = {
    'run_id': 'abc123',
    'items': [1, 2, 3],
    'meta': {'agent': 'v2', 'model': 'gpt-4o'}
}

with open('output.json', 'w', encoding='utf-8') as f:
    json.dump(
        output_data, f,
        indent=2,
        ensure_ascii=False
    )
print('Written output.json')

JSON 디코딩 오류 처리

에이전트 처리 흐름에서는 형식이 잘못된 JSON 파일이 흔히 발생합니다. 쓰기가 완료되지 않았거나, 다운로드가 잘렸거나, 인코딩 문제가 원인일 수 있습니다. 항상 json.load()를 try/except로 감싸고, 디버깅할 수 있도록 파일 경로가 포함된 명확한 오류 메시지를 제공하십시오.

import json
from pathlib import Path

def safe_load_json(file_path):
    path = Path(file_path)
    try:
        with open(path, 'r', encoding='utf-8') as f:
            return json.load(f)
    except json.JSONDecodeError as e:
        print(f'Invalid JSON in {path}: line {e.lineno}, col {e.colno}')
        print(f'  Error: {e.msg}')
        # Show the problem area
        content = path.read_text(encoding='utf-8')
        lines = content.split('\n')
        if e.lineno <= len(lines):
            print(f'  Content: {lines[e.lineno-1][:80]}')
        return None
    except FileNotFoundError:
        print(f'File not found: {path}')
        return None

# --- demo ---
Path('good.json').write_text('{"model": "gpt-4o"}', encoding='utf-8')
Path('bad.json').write_text('{"model": "gpt-4o", }', encoding='utf-8')

print('Loading good.json:', safe_load_json('good.json'))
print('Loading bad.json:', safe_load_json('bad.json'))

JSONL(JSON 줄) 형식 읽기

많은 인공지능 API와 데이터 처리 흐름은 JSONL(JSON Lines)을 사용합니다. 한 줄에 JSON 객체 하나를 저장하는 형식입니다. 이 형식은 스트리밍을 지원하며 전체 파일을 메모리에 불러오지 않고 한 줄씩 쉽게 처리할 수 있습니다. 각 줄은 완전하고 독립적인 JSON 객체입니다.

import json

with open('events.jsonl', 'w', encoding='utf-8') as f:
    f.write('{"event": "start"}\n{"event": "stop"}\nnot json\n')

results = []
with open('events.jsonl', 'r', encoding='utf-8') as f:
    for line_num, line in enumerate(f, 1):
        line = line.strip()
        if not line:
            continue
        try:
            event = json.loads(line)
            results.append(event)
        except json.JSONDecodeError as e:
            print(f'Bad JSON on line {line_num}: {e}')

print(f'Loaded {len(results)} events')

with open('output.jsonl', 'w', encoding='utf-8') as f:
    for record in results:
        f.write(json.dumps(record, ensure_ascii=False) + '\n')

일반 텍스트 파일 읽기

일반 텍스트는 로그, 프롬프트, 보고서 및 설정 파일에 사용되는 가장 단순한 형식입니다. .read()로 파일 전체를 읽거나 한 줄씩 처리할 수 있습니다. 대용량 파일에서는 메모리 사용량을 일정하게 유지하도록 항상 한 줄씩 처리하는 방식을 사용하십시오.

from pathlib import Path

Path('system_prompt.txt').write_text('You are a helpful agent.', encoding='utf-8')
with open('agent.log', 'w', encoding='utf-8') as f:
    f.write('INFO: boot\nERROR: disk full\nCRITICAL: crash\nINFO: recovered\n')

prompt = Path('system_prompt.txt').read_text(encoding='utf-8')
print(f'Prompt length: {len(prompt)} characters')

error_lines = []
with open('agent.log', 'r', encoding='utf-8') as f:
    for line in f:
        line = line.rstrip()
        if not line:
            continue
        if 'ERROR' in line or 'CRITICAL' in line:
            error_lines.append(line)

print(f'Found {len(error_lines)} error lines')

with open('summary.txt', 'w', encoding='utf-8') as f:
    f.write('Agent Run Summary\n')
    f.write('=' * 40 + '\n')
    for error in error_lines[:10]:
        f.write(f'  {error}\n')
print('Summary written')

BOM(바이트 순서 표시) 처리

Excel이나 Windows 도구에서 내보낸 파일은 시작 부분에 보이지 않는 BOM(바이트 순서 표시) 문자 \ufeff가 포함된 경우가 많습니다. 이를 처리하지 않으면 CSV 파싱 시 첫 번째 필드 이름이 손상됩니다. 자동으로 제거하려면 encoding='utf-8-sig'를 사용하십시오.

import csv

with open('windows_export.csv', 'wb') as f:
    f.write('name,email,age\nAlice,alice@x.com,30\n'.encode('utf-8'))
with open('file.txt', 'wb') as f:
    f.write(b'\xef\xbb\xbfhello')

with open('windows_export.csv', 'r', encoding='utf-8') as f:
    reader = csv.DictReader(f)
    first = next(reader)
    print(list(first.keys()))

with open('windows_export.csv', 'r', encoding='utf-8-sig') as f:
    reader = csv.DictReader(f)
    first = next(reader)
    print(list(first.keys()))

content = open('file.txt', 'rb').read()
if content.startswith(b'\xef\xbb\xbf'):
    content = content[3:]
text = content.decode('utf-8')
print('Decoded:', text)

인코딩 오류 처리

출처를 알 수 없는 파일을 읽을 때는 인코딩 오류가 흔히 발생합니다. open()의 errors 매개변수는 처리 방식을 제어합니다. 'replace'는 잘못된 문자를 ?로 바꾸고, 'ignore'는 해당 문자를 제거하며, 'backslashreplace'는 이스케이프합니다. 엄격하게 검증하려면 기본값인 'strict'를 사용하십시오.

from pathlib import Path

def read_with_fallback(file_path):
    path = Path(file_path)

    # Try UTF-8 first
    try:
        return path.read_text(encoding='utf-8')
    except UnicodeDecodeError:
        pass

    # Try Latin-1 (handles most European files)
    try:
        return path.read_text(encoding='latin-1')
    except UnicodeDecodeError:
        pass

    # Last resort: replace bad characters
    text = path.read_text(encoding='utf-8', errors='replace')
    print(f'Warning: {path.name} had encoding errors (chars replaced)')
    return text

# --- demo ---
Path('notes_utf8.txt').write_text('Notes: café, naïve, résumé', encoding='utf-8')
text = read_with_fallback('notes_utf8.txt')
print(f'Read {len(text)} chars: {text!r}')

형식이 잘못된 CSV 파일 처리

실제 CSV 파일에는 추가 쉼표, 누락된 필드, 일관되지 않은 따옴표, 구분자 혼용 등의 문제가 있을 수 있습니다. quoting 및 error_bad_lines 옵션을 사용하고, 행 파싱을 try/except로 감싸 잘못된 행을 적절히 건너뛰십시오.

import csv

with open('messy_data.csv', 'w', newline='') as f:
    f.write('name,email,score\nAlice,alice@x.com,88\nBob,,90\nCarol,carol@x.com,notanumber\n')

valid_rows = []
error_count = 0

with open('messy_data.csv', 'r', encoding='utf-8', newline='') as f:
    reader = csv.DictReader(f)
    expected_fields = {'name', 'email', 'score'}

    for line_num, row in enumerate(reader, start=2):
        try:
            if not all(row.get(f, '').strip() for f in expected_fields):
                raise ValueError(f'Missing required field in row {line_num}')
            score = float(row['score'])
            valid_rows.append({
                'name': row['name'].strip(),
                'email': row['email'].strip().lower(),
                'score': score
            })
        except (ValueError, KeyError) as e:
            error_count += 1
            print(f'Skipping row {line_num}: {e}')

print(f'Valid: {len(valid_rows)}, Errors: {error_count}')

빠른 확인: CSV DictReader와 reader 비교

CSV 파싱 옵션에 대한 이해도를 확인합니다.

파일 형식 처리 복습

이제 에이전트의 주요 파일 형식을 모두 파싱하고 쓸 수 있습니다.

  • CSV: 딕셔너리 행에는 csv.DictReader, 출력에는 csv.DictWriter를 사용하고, 열 때는 항상 newline=''을 사용합니다
  • JSON: 파싱에는 json.load(f), 쓰기에는 json.dump(obj, f, indent=2)를 사용하고 JSONDecodeError를 처리합니다
  • JSONL: 각 줄을 json.loads(line)로 읽고 파싱하며, 스트리밍 데이터에 적합합니다
  • 일반 텍스트: 작은 파일에는 .read(), 큰 파일에는 한 줄씩 순회하는 방식을 사용합니다
  • BOM: Windows에서 내보낸 파일에는 encoding='utf-8-sig'를 사용합니다
  • 인코딩 오류: UTF-8을 시도하고 latin-1로 대체하거나 errors='replace'를 사용합니다

자주 묻는 질문

“파일 형식 처리: CSV, JSON, TXT” 강의는 무료인가요?

네 — “파일 형식 처리: CSV, JSON, TXT” 전체 내용을 이 웹사이트에서 무료로 읽을 수 있습니다. 인터랙티브하게 실습하려면(내장 코드 에디터와 24/7 AI 튜터), CoddyKit PRO로 업그레이드하면 AI Agents 강의 전체를 잠금 해제할 수 있습니다. AI Agents 강의에는 총 4개의 강의가 포함되어 있습니다.

“파일 형식 처리: CSV, JSON, TXT”에서 뭘 배우나요?

csv 모듈, json.load/dump, 에이전트 도구를 위한 안전한 텍스트 인코딩을 다룹니다. 브라우저에서 직접 실행하는 실습 코드로 AI Agents을(를) 배우며, 24/7 AI 튜터가 강의를 진행하면서 질문에 답변해줍니다.

AI Agents을(를) 시작하는 데 경험이 필요한가요?

사전 경험은 필요하지 않습니다. CoddyKit의 AI Agents은(는) 초급자부터 고급 학습자까지를 위해 구성되어 있으므로, 여기서 시작하거나 처음부터 시작할 수 있으며 자신의 속도대로 진행할 수 있습니다. 이것은 4개 중 3번째 강의입니다.

“파일 형식 처리: CSV, JSON, TXT” 강의는 얼마나 걸리나요?

대부분의 CoddyKit 강의는 약 5~10분이 소요됩니다. 각 강의는 간결하고 인터랙티브하여 꾸준한 진행이 가능하며, 웹과 앱에서 중단한 부분부터 바로 시작할 수 있습니다.

이 AI Agents 강의에서 코드를 작성하고 실행할 수 있나요?

네. 모든 AI Agents 강의에는 내장 코드 에디터가 포함되어 있으므로, 브라우저에서 바로 실제 코드를 작성하고 실행한 후 즉시 AI 피드백을 받을 수 있습니다 — 로컬 설정이 필요 없습니다.

이 강의의 모든 강의

  1. 에이전트 환경에서 파일 읽기 및 쓰기
  2. 디렉터리 탐색 및 파일 찾기
  3. 파일 형식 처리: CSV, JSON, TXT
  4. 오류 처리를 적용한 안전한 파일 작업
← AI Agents(으)로 돌아가기