পাঠ ০৭ · ২৫-এর মধ্যে · মডিউল ১

ফাইল পড়া ও লেখা

File I/O — text, CSV, JSON
৬ মিনিট পড়া শুরু · Beginner ব্রাউজারে কোড চালান

এই পাঠে যা শিখবেন

  • Text ফাইল পড়া ও লেখা — open() ও context manager
  • Mode ও encoding — কখন কোনটা
  • CSV ফাইল — csv module-এ পড়া
  • JSON ফাইল — Python dict ↔ disk
  • pathlib — modern path management
  • AI dataset (CSV, JSON, JSONL) load করার pattern

১ · Text ফাইল লেখা ও পড়া

File I/O — disk-এর সাথে কথোপকথন। Python-এ আদর্শ pattern: context managerContext Manager"with" statement-এর সাথে ব্যবহৃত object — ব্লক শেষে cleanup auto। file close, lock release — সাধারণ ব্যবহার। __enter__, __exit__ dunder methods। (with) — auto-close।

Python
# লেখা
with open("hello.txt", "w", encoding="utf-8") as f:
    f.write("নমস্কার, পাইথন!\n")
    f.write("দ্বিতীয় লাইন\n")
    f.write("তৃতীয় লাইন\n")

# পুরো পড়া
with open("hello.txt", "r", encoding="utf-8") as f:
    content = f.read()
print(content)

# লাইন-বাই-লাইন
print("--- লাইন আকারে ---")
with open("hello.txt", "r", encoding="utf-8") as f:
    for i, line in enumerate(f, 1):
        print(f"{i}: {line.rstrip()}")

    
with block শেষে file auto-close — এমনকি error হলেও। বিনা with — file leak, OS-এ resource ফাঁক। সবসময় with ব্যবহার করুন।

২ · Mode-এর সংক্ষেপ

৬টি মৌলিক mode

"r" — read (default)। ফাইল না থাকলে error।
"w" — write। ফাইল থাকলে overwrite!
"a" — append। শেষে যোগ।
"x" — exclusive create। থাকলে error।
"b" — binary mode (image, audio, model weights)।
"r+"/"w+" — read+write।

"w" mode — পুরনো content চিরতরে মুছে দেয়। গুরুত্বপূর্ণ ফাইলে "x" ব্যবহার করুন (থাকলে error দেবে, accidental overwrite থেকে বাঁচায়)।

৩ · Encoding — Bangla-র জন্য বিশেষ গুরুত্ব

Computer-এ সব text বাইটে রাখা — কিন্তু কোন বাইট কোন অক্ষর? — encodingEncodingঅক্ষর ↔ বাইটের mapping। ASCII (১২৮ char), Latin-1 (২৫৬), UTF-8 (১,১১,০০০+ char — সব ভাষা)। আজকের default UTF-8।।

Python
# Bangla লেখা — অবশ্যই UTF-8
text = "বাংলা টেক্সট: কেমন আছেন?"

with open("bangla.txt", "w", encoding="utf-8") as f:
    f.write(text)

# UTF-8-এ পড়া — ঠিক
with open("bangla.txt", "r", encoding="utf-8") as f:
    print(f.read())

# Bytes — internal representation
with open("bangla.txt", "rb") as f:
    raw = f.read()
print(f"মোট bytes: {len(raw)}")
print(f"প্রথম ১০: {raw[:10]}")

    
Windows-এ default encoding প্রায়ই cp1252 (Latin-1)। Bangla-তে garbled text। সবসময় encoding="utf-8" explicitly দিন।

৪ · CSV ফাইল — table data

Python
import csv

# লেখা
rows = [
    ["name", "age", "score"],
    ["রহিম", 22, 85],
    ["ফাতেমা", 21, 92],
    ["করিম", 23, 78],
]

with open("students.csv", "w", encoding="utf-8", newline="") as f:
    writer = csv.writer(f)
    writer.writerows(rows)

# পড়া
print("--- csv.reader ---")
with open("students.csv", "r", encoding="utf-8") as f:
    reader = csv.reader(f)
    for row in reader:
        print(row)

# DictReader — header → key
print("\n--- DictReader ---")
with open("students.csv", "r", encoding="utf-8") as f:
    reader = csv.DictReader(f)
    for row in reader:
        print(f"{row['name']} → {row['score']}")

    
AI/ML data বেশিরভাগ CSV-তে। সবচেয়ে জনপ্রিয় library — Pandas — internally csv module-এর উপর। L13 থেকে আমরা Pandas দেখব।

৫ · JSON ফাইল — structured data

Python
import json

# Python dict → JSON file
config = {
    "model": "BERT-base",
    "hyperparameters": {
        "lr": 0.0001,
        "batch_size": 32,
        "epochs": 10
    },
    "languages": ["bangla", "english"]
}

with open("config.json", "w", encoding="utf-8") as f:
    json.dump(config, f, indent=2, ensure_ascii=False)

# JSON file → Python dict
with open("config.json", "r", encoding="utf-8") as f:
    loaded = json.load(f)

print(loaded)
print(f"Learning rate: {loaded['hyperparameters']['lr']}")

# JSONL — প্রতি লাইনে একটি JSON object (AI dataset standard)
records = [
    {"id": 1, "text": "প্রথম sentence"},
    {"id": 2, "text": "দ্বিতীয় sentence"},
    {"id": 3, "text": "তৃতীয় sentence"},
]

with open("data.jsonl", "w", encoding="utf-8") as f:
    for rec in records:
        f.write(json.dumps(rec, ensure_ascii=False) + "\n")

# পড়া — generator
print("\n--- JSONL ---")
with open("data.jsonl", "r", encoding="utf-8") as f:
    for line in f:
        rec = json.loads(line)
        print(rec)

    
JSON = ডেটার "package"। JSONL = প্যাকেজের লাইনের পর লাইন। বড় AI dataset (HuggingFace, OpenAI) JSONL-এ — generator দিয়ে stream পড়া যায়।
ফাইল ফরম্যাট ও কোন কাজে Choose the right format Python data 📄 .txt unstructured text log, raw text data 📊 .csv tabular data Excel, ML dataset 🗂️ .json structured config, API, nested 📜 .jsonl line-delimited JSON LLM dataset, log 🔐 .bin / .pt model weights image, audio ⚡ .parquet columnar binary big-data, fast
পাঁচ format — পাঁচ ব্যবহার। AI projects-এ JSON config + CSV/Parquet data + binary weights।

৬ · pathlib — modern path handling

Python
from pathlib import Path

# Path object — OS-independent
data_dir = Path("datasets")
file_path = data_dir / "students.csv"        # / operator!

print(file_path)
print(file_path.suffix)                       # .csv
print(file_path.stem)                         # students
print(file_path.exists())

# Directory তৈরি
data_dir.mkdir(exist_ok=True)

# পড়া — Path-এর built-in
content = Path("hello.txt").read_text(encoding="utf-8")
print(content[:30])

# সব .csv খুঁজে বের
for csv_file in Path(".").glob("*.csv"):
    print(csv_file)

    
pathlib.Path Python 3.4+ থেকে। OS-independent — Windows-এ \ ও Linux-এ / auto-handle। আজকের best practice — os.path-এর জায়গায়।

৭ · AI-তে file I/O-র প্রয়োগ

  • Dataset loading: CSV (tabular), JSONL (LLM), parquet (big-data)।
  • Configuration: JSON/YAML hyperparameter।
  • Model checkpoint: binary .pt, .h5, .safetensors।
  • Logging: training logs, metrics CSV।
  • Cache: embedding pre-compute → disk-এ।
  • Output: prediction CSV → submission।

ভাবনার প্রশ্ন

প্রতিটি প্রশ্ন নিজে কিছুক্ষণ ভাবুন — তারপর "→ উত্তর" চাপুন।

প্র ০১ with open(...) বনাম open() + manual close — কেন context manager universally preferred? Resource leak কী, ও AI training-এ কীভাবে কামড় দেয়?

Context manager — Python-এর সবচেয়ে underrated feature। PEP 343 (২০০৫) থেকে। ভাল কোড ও bad কোডের সীমারেখা।

Resource leak কী?

  • OS-এর প্রতিটি open file = একটি "file descriptor" (FD)।
  • OS-এর FD limit আছে — Linux default 1024।
  • Close না করলে — ধীরে ধীরে শেষ হয়।
  • "Too many open files" error — production crash।

Without context manager:

f = open("data.txt")
process(f.read())
f.close()        # বহু সমস্যা:
                 # 1. process() exception দিলে close চলে না
                 # 2. মনে রাখা দরকার
                 # 3. early return — close মিস

With context manager:

with open("data.txt") as f:
    process(f.read())
# yes — exception হলেও close
# yes — early return-এ close
# yes — visual scope spell out

Mechanism — __enter__/__exit__:

class MyContext:
    def __enter__(self):
        # setup (open file, acquire lock)
        return self
    def __exit__(self, exc_type, exc, tb):
        # cleanup (close, release)
        return False    # exception propagate

AI training-এ resource leak-এর কামড়:

  • Training loop-এ file open করলে: ১০,০০০ epoch → ১০,০০০ FD leak → crash।
  • DataLoader worker-এ: প্রতি batch file open — কিন্তু close না হলে।
  • Weights & Biases / TensorBoard: log writer সঠিক close না হলে — buffer flush হয় না, data lost।
  • GPU memory: tensor leak — analogous problem। PyTorch-এ torch.cuda.empty_cache()।

Beyond files — context manager-এর ব্যবহার:

  • with torch.no_grad(): — gradient computation disable।
  • with model.eval(): — eval mode।
  • with timer(): — section timing।
  • with Lock(): — thread synchronization।
  • with db.transaction(): — atomic operation।

Custom context manager — easy way:

from contextlib import contextmanager

@contextmanager
def timer(name):
    import time
    start = time.time()
    yield
    print(f"{name}: {time.time()-start:.4f}s")

with timer("training"):
    train_one_epoch()

Multiple resources:

# একসাথে দুই ফাইল
with open("in.txt") as f_in, open("out.txt", "w") as f_out:
    f_out.write(f_in.read().upper())

# Python 3.10+ — parenthesized
with (
    open("a.txt") as a,
    open("b.txt") as b,
    open("c.txt") as c,
):
    ...

মূল উপলব্ধি: with = "guarantee cleanup"। AI long-running training-এ অপরিহার্য। File, lock, DB, GPU memory — যেকোনো resource। মন দিয়ে গাঁথা — লাখ epoch-এও crash নেই।

প্র ০২ JSON, JSONL, Parquet, HDF5 — চারটি data format। Big AI dataset-এর জন্য কোনটা সেরা? Trade-off কী — readability, size, speed, schema-evolution?

Data format choice = AI infrastructure-এর foundational decision। ভুল choice = TB-scale data দিয়ে বছর হারানো।

JSON — universal, readable:

  • ✓ Human-readable, debug সহজ।
  • ✓ Universal — সব ভাষায়।
  • ✓ Schema flexible।
  • ✗ Large — text overhead।
  • ✗ Slow parse — character-by-character।
  • ✗ Single object — পুরোটা memory-তে।

JSONL — streaming-friendly:

  • প্রতি লাইনে একটি JSON object।
  • ✓ Stream-friendly — generator দিয়ে।
  • ✓ Append চলে — concurrent write।
  • ✓ Partial read — corrupt লাইন skip।
  • ✓ HuggingFace, OpenAI fine-tuning — standard।
  • ✗ Still text — large size।
  • ✗ Random access নেই।

Parquet — columnar binary:

  • Apache project (২০১৩) — Hadoop ecosystem থেকে।
  • ✓ Compressed — JSON-এর ১০-১০০× ছোট।
  • ✓ Columnar — শুধু দরকারি column পড়া যায়।
  • ✓ Schema-aware — type checking।
  • ✓ Predicate pushdown — filter at read time।
  • ✓ Pandas, Spark, Dask — সবাই native।
  • ✗ Binary — debug কঠিন।
  • ✗ Append কঠিন।

HDF5 — scientific:

  • NASA-র scientific data থেকে এসেছে।
  • ✓ Hierarchical — ফাইলের মধ্যে dataset tree।
  • ✓ Random access — slice load।
  • ✓ Multi-dimensional array native।
  • ✓ TF/PyTorch compatible।
  • ✗ Concurrent write কঠিন।
  • ✗ Library-heavy।

আধুনিক alternatives:

  • Arrow/Feather: in-memory columnar — দ্রুত। Pandas-এর সাথে natural।
  • Zarr: Cloud-native HDF5 alternative। Object storage friendly।
  • WebDataset: tar archive — streaming + sharded。 PyTorch-এর জন্য আদর্শ।
  • safetensors: Hugging Face — secure, fast tensor format।

Use case-ভিত্তিক recommendation:

  • Configuration: JSON/YAML/TOML।
  • LLM training data: JSONL — streaming।
  • Tabular ML data < 10 GB: Parquet।
  • Tabular ML data > 100 GB: Parquet + partitioning।
  • Scientific multi-D arrays: HDF5/Zarr।
  • Image/audio batches: WebDataset।
  • Model weights: safetensors > .pt।

Performance comparison (১ লক্ষ tabular row):

  • JSON: ৫০ MB, ১.৫ s read।
  • JSONL: ৫০ MB, ১.০ s।
  • CSV: ৩০ MB, ০.৫ s।
  • Parquet: ৩ MB, ০.০৫ s — best।

Schema evolution challenges:

  • JSON/JSONL — flexible, কিন্তু runtime error risk।
  • Parquet — schema embedded, evolution support।
  • Arrow — strict typing।
  • Pydantic + JSONL = balance।

মূল উপলব্ধি: "One format fits all" নেই। Workflow stage-অনুযায়ী format। Raw collection JSONL → cleaned/processed Parquet → training তৈরি Arrow। AI infra-র এই pipeline বুঝলে — petabyte data scale-এ যেতে পারবেন।

প্র ০৩ Encoding সমস্যা (UnicodeDecodeError) Python-এর একটি classic pain. UTF-8, UTF-16, ASCII, Latin-1 — পার্থক্য কী? Bangla প্রকল্পে কোন সাবধানতা?

Encoding — software engineering-এর সবচেয়ে underestimated topic। ভুল encoding = silent data corruption।

মূল ধারণা:

  • Computer-এ "অক্ষর" নেই — শুধু bytes (০-২৫৫)।
  • Encoding = "এই byte কোন অক্ষর?" mapping।
  • ভুল encoding-এ পড়া = mojibake (গরবলা)।

Encoding-এর historical evolution:

  • ASCII (১৯৬৩): ৭-bit, ১২৮ char। English only।
  • Latin-1/ISO-8859-1: ৮-bit, ২৫৬ char। European।
  • Windows-1252: Microsoft variant। প্রায়ই Western default।
  • ISCII, ASCII-Bangla: পুরনো Bangla — incompatible।
  • UTF-8 (১৯৯৩): Unicode + ASCII compatible. ১-৪ bytes/char।
  • UTF-16: Java, JavaScript। ২-৪ bytes।

UTF-8 কেন winner?

  • ASCII subset — backward compatible।
  • Variable length — English এ ১ byte, Bangla এ ৩ bytes।
  • Self-synchronizing — partial corrupt-এ recovery।
  • Web-এর de facto (98%+ pages)।
  • Python ৩-এর default।

Bangla-র specifics:

  • Bangla Unicode range: U+0980 - U+09FF।
  • প্রতি অক্ষর — UTF-8-এ ৩ bytes (সাধারণত)।
  • Conjuncts (যুক্তবর্ণ) — multiple codepoints।
  • Normalization (NFC, NFD) — same character ভিন্ন bytes।

সাধারণ Bangla bug:

# Windows default cp1252 → Bangla broken
with open("bangla.txt") as f:
    text = f.read()    # UnicodeDecodeError

# Always explicit
with open("bangla.txt", encoding="utf-8") as f:
    text = f.read()    # ✓

Detection ও handling:

# Detect — chardet library
import chardet
with open("unknown.txt", "rb") as f:
    raw = f.read()
detected = chardet.detect(raw)
print(detected)    # {'encoding': 'utf-8', 'confidence': 0.99}

# Errors handling
text = raw.decode("utf-8", errors="replace")    # ? for invalid
text = raw.decode("utf-8", errors="ignore")     # silent skip

BOM (Byte Order Mark):

  • UTF-8 BOM: \xef\xbb\xbf
  • Excel CSV save করলে — BOM যোগ করে। Python-এ extra char।
  • Solution: encoding="utf-8-sig"

Normalization issue:

import unicodedata

# একই display, ভিন্ন bytes
a = "নী"           # NFC — single codepoint
b = "নী"           # NFD — two codepoints

print(a == b)                                  # False!
print(unicodedata.normalize("NFC", a) ==
      unicodedata.normalize("NFC", b))         # True

AI/ML-এ encoding সাবধানতা:

  • Tokenizer training — সঠিক normalization জরুরি।
  • Multilingual models — UTF-8 explicit।
  • Web scraping — chardet detect।
  • Database export — UTF-8 with BOM-এর জন্য সাবধান।
  • HuggingFace tokenizer — pre-tokenization-এ Unicode normalize।

সর্বদা practice:

  • encoding="utf-8" EVERYWHERE।
  • Source file BOM-free UTF-8।
  • Locale-independent code (LANG=C.UTF-8)।
  • Test multilingual data।
  • Normalize Unicode (NFC) at boundary।

মূল উপলব্ধি: Encoding bugs silent ও subtle। Bangla project-এ — UTF-8 explicit always। Decode early at boundary, work in str, encode at boundary again। "Garbage in, garbage out" — encoding-এর জগতে literal।

প্র ০৪ "Open file in loop" anti-pattern বনাম "open once, iterate" — performance ও correctness-এ পার্থক্য কী? Memory-mapped file কখন? AI dataset training-এ এই choice-এর প্রভাব?

File access patterns — performance-এর hidden lever। AI-তে correct pattern = ১০× faster training।

Anti-pattern: open in loop:

# খুব খারাপ — প্রতি batch-এ file open
for batch_idx in range(1000):
    with open("data.csv") as f:
        data = f.read()
    process(data)
# 1000× file open — slow, FD pressure

সঠিক — open একবার:

# ভাল
data = []
with open("data.csv") as f:
    for line in f:
        data.append(parse(line))

for batch in batches(data):
    process(batch)

কিন্তু — সমস্যা: data যদি ১০০ GB?

  • সব memory-তে — RAM exhausted।
  • Generator pattern দরকার।

Streaming pattern:

def stream_batches(path, batch_size=32):
    with open(path) as f:
        batch = []
        for line in f:
            batch.append(parse(line))
            if len(batch) == batch_size:
                yield batch
                batch = []
        if batch:
            yield batch

for batch in stream_batches("huge.jsonl"):
    train_step(batch)

Memory-mapped file (mmap):

import mmap

with open("huge.bin", "rb") as f:
    mm = mmap.mmap(f.fileno(), 0, access=mmap.ACCESS_READ)
    # OS lazily loads pages as accessed
    # Random access to TBs without memory pressure
    chunk = mm[1000:2000]
    mm.close()

mmap-এর জাদু:

  • OS file pages-কে virtual memory-তে map করে।
  • Read করলেই — page-fault → disk → cache।
  • Multiple process একই file share করতে পারে।
  • Random access constant time — even for 100 GB।

AI training data access patterns:

  • Sequential: stream — generator, simplest।
  • Random shuffle: all-in-memory if fits, else mmap বা index-based।
  • Sharded: WebDataset — tar shards, parallel read।
  • Distributed: S3/GCS streaming, prefetch।

PyTorch DataLoader internals:

  • num_workers — multi-process file read।
  • pin_memory — pinned buffer for GPU transfer।
  • prefetch — পরের batch প্রস্তুত করে।
  • persistent_workers — worker reuse।

I/O bottleneck-এর symptom:

  • GPU utilization < 50% — data pipeline bottleneck।
  • Disk activity 100% — I/O bound।
  • Solution: parallel read, faster format (Parquet), SSD।

Benchmarking command:

# Linux
iostat -x 1
nvidia-smi --query-gpu=utilization.gpu --format=csv -l 1

Best practices summary:

  • Open once, iterate inside.
  • Generator for streaming।
  • mmap for random access on large files।
  • Parquet/Arrow for tabular।
  • WebDataset for shard-based training।
  • Profile before optimizing।

মূল উপলব্ধি: File I/O = AI training-এর hidden bottleneck। Compute powerful, কিন্তু data feed slow → GPU idle। Right pattern (open once, generator, mmap, sharding) = full GPU utilization। L19+ Notebook ও Pandas-এ আমরা এই pattern বাস্তবিক দেখব।

অনুশীলন

  1. Word counter: একটি text ফাইল লিখুন (৫টি বাংলা বাক্য)। তারপর পড়ে — মোট কতটি লাইন ও word আছে গণনা করুন।
    # লেখা
    text = """বাংলা আমার মাতৃভাষা।
    পাইথন একটি জনপ্রিয় ভাষা।
    AI ভবিষ্যৎ গড়বে।
    ABCL TECH-এ আমরা শিখছি।
    ফাইল I/O সহজ।"""
    
    with open("sample.txt", "w", encoding="utf-8") as f:
        f.write(text)
    
    # পড়া + গণনা
    with open("sample.txt", "r", encoding="utf-8") as f:
        lines = f.readlines()
    
    n_lines = len(lines)
    n_words = sum(len(line.split()) for line in lines)
    print(f"লাইন: {n_lines}, শব্দ: {n_words}")
  2. JSON config: একটি hyperparameter dict তৈরি করুন (lr, batch, epochs)। JSON-এ save ও পরে load করুন।
    import json
    
    cfg = {"lr": 0.001, "batch": 32, "epochs": 50}
    
    with open("hparams.json", "w") as f:
        json.dump(cfg, f, indent=2)
    
    with open("hparams.json") as f:
        loaded = json.load(f)
    print(loaded)
    print(f"Learning rate: {loaded['lr']}")
  3. CSV → average: একটি CSV-তে student scores লিখুন। পড়ে — গড় score বের করুন DictReader দিয়ে।
    import csv
    
    # তৈরি
    rows = [
        ["name", "score"],
        ["A", 85], ["B", 92], ["C", 78], ["D", 67], ["E", 95]
    ]
    with open("scores.csv", "w", newline="", encoding="utf-8") as f:
        csv.writer(f).writerows(rows)
    
    # গড়
    with open("scores.csv", encoding="utf-8") as f:
        reader = csv.DictReader(f)
        scores = [int(row["score"]) for row in reader]
    
    avg = sum(scores) / len(scores)
    print(f"গড় স্কোর: {avg:.2f}")    # 83.40

আরও পড়ুন · ABCL TECH-এ আপনার পরবর্তী পদক্ষেপ

কোড রানার কাজ না করলে? ব্রাউজারে কাজ না করলে Google Colab ব্যবহার করুন।
পূর্ববর্তী পাঠ
পাঠ ০৬ · List comprehension ও iterator