aidoc.uz

3-qism · Professional Python·11-bob

Fayllar, yo'llar va ma'lumot formatlari

pathlib bilan yo'llar, fayllarni ochish rejimlari va kodlash, katta fayllarni oqim bilan o'qish, CSV, JSON va JSONL, pickle xavfi, Parquet va boshqa formatlar, xavfsiz (atomic) yozish.

ML loyihasining katta qismi — fayllar bilan ishlash: datasetlarni o'qish, tozalangan ma'lumotni saqlash, model checkpoint'lari, tajriba natijalari, konfiguratsiyalar, loglar. Bu bobda fayl tizimi bilan xavfsiz va platformadan mustaqil ishlashni hamda AI/ML'da eng ko'p uchraydigan formatlarni o'rganamiz.

▶ Video dars· Corey Schafer· 34:51· ingliz tilida
Python Tutorial: Pathlib - The Modern Way to Handle File Paths

pathlib bilan fayl yo'llari: yaratish, qidirish, o'qish va yozish — bobning 1-bo'limidagi zamonaviy usul batafsil.

YouTube'da ochish ↗

1. pathlib — yo'llar bilan zamonaviy ishlash#

Eski kodlarda yo'llar satr sifatida va os.path bilan yig'iladi:

import os
path = os.path.join("data", "raw", "reviews.csv")   # eski uslub

Zamonaviy usul — pathlib.Path obyekti:

from pathlib import Path
 
DATA_DIR = Path("data")
p = DATA_DIR / "raw" / "reviews.csv"    # / operatori yo'lni birlashtiradi
 
p.name           # 'reviews.csv'
p.stem           # 'reviews'
p.suffix         # '.csv'
p.parent         # Path('data/raw')
p.with_suffix(".parquet")   # Path('data/raw/reviews.parquet')
p.parts          # ('data', 'raw', 'reviews.csv')

Path Windows'da \, Linux/macOS'da / ishlatadi — kodingiz ikkalasida ham ishlaydi.

Fayl tizimi amallari#

p.exists()                  # mavjudmi
p.is_file(), p.is_dir()
p.stat().st_size            # hajmi, baytda
p.resolve()                 # to'liq (absolyut) yo'l
 
out = Path("outputs") / "run-01"
out.mkdir(parents=True, exist_ok=True)   # ichma-ich papkalar; mavjud bo'lsa xato yo'q
 
p.read_text(encoding="utf-8")            # butun faylni satr sifatida
p.write_text("salom", encoding="utf-8")  # yozish (eski mazmun o'chadi)
p.read_bytes(), p.write_bytes(b"...")
 
p.rename(p.with_name("old.csv"))
p.unlink(missing_ok=True)                # faylni o'chirish

Fayllarni qidirish#

data = Path("data")
list(data.glob("*.csv"))           # faqat shu papkadagi .csv'lar
list(data.rglob("*.jsonl"))        # barcha ichki papkalarda ham
sorted(data.glob("img_*.png"))     # tartib kafolatlanmaydi — saralang!
 
for f in data.iterdir():           # papka ichidagilar
    if f.is_file():
        print(f.name, f.stat().st_size)

Skript joylashuviga nisbatan yo'l#

# src/myproject/config.py
from pathlib import Path
 
PROJECT_ROOT = Path(__file__).resolve().parents[2]   # config.py → myproject → src → loyiha
DATA_DIR = PROJECT_ROOT / "data"

Path("data") — joriy ishchi papkaga nisbatan; skriptni boshqa papkadan ishga tushirsangiz, boshqa joyni ko'rsatadi. __file__ga nisbatan yo'l esa har doim bir xil.

2. open() — fayllarni ochish#

with open("notes.txt", "w", encoding="utf-8") as f:
    f.write("Birinchi qator\n")
    f.write("Ikkinchi qator\n")
 
with open("notes.txt", encoding="utf-8") as f:      # standart rejim — "r"
    content = f.read()

Rejimlar#

RejimMa'nosiFayl yo'q bo'lsaFayl bor bo'lsa
"r"O'qish (standart)XatoO'qiydi
"w"YozishYaratadiMazmunni o'chiradi!
"a"Oxiriga qo'shishYaratadiOxiriga yozadi
"x"Faqat yangi fayl yaratishYaratadiXato (tasodifan ustidan yozishdan himoya)
"r+"O'qish va yozishXato—
+ "b"Ikkilik (binary): "rb", "wb"baytlar, encodingsiz

Kodlash (encoding) — har doim yozing#

3-bobda aytilgandek: matnli faylni ochganda har doim encoding="utf-8" yozing. Aks holda Python operatsion tizimning standart kodlashini ishlatadi (Windows'da ko'pincha cp1251 yoki cp1252) va o'zbekcha/ruscha matn buziladi.

Kodlashi noma'lum fayl uchun:

with open(path, encoding="utf-8", errors="replace") as f:   # buzilgan baytlar → �
    text = f.read()

Excel'dan saqlangan CSV ko'pincha utf-8-sig (boshida BOM belgisi bilan) bo'ladi — birinchi ustun nomi "name" bo'lib qolsa, sabab shu: encoding="utf-8-sig" ishlating.

O'qish usullari#

with open(path, encoding="utf-8") as f:
    text = f.read()             # butun fayl — bitta satr (kichik fayllar uchun)
 
with open(path, encoding="utf-8") as f:
    lines = f.readlines()       # qatorlar ro'yxati (\n bilan) — butun fayl xotirada
 
with open(path, encoding="utf-8") as f:
    for line in f:              # ✅ qatorma-qator — xotira tejamkor (7-bob!)
        process(line.rstrip("\n"))

Fayl obyekti — iterator (7-bob): for line in f bir vaqtda faqat bitta qatorni xotirada ushlaydi. 50 GB log faylni ham shunday o'qish mumkin.

Ikkilik fayllar va bo'laklab o'qish#

import hashlib
 
 
def sha256(path: Path, chunk_size: int = 1 << 20) -> str:
    """Katta faylning hash'ini 1 MB bo'laklab hisoblaydi."""
    h = hashlib.sha256()
    with open(path, "rb") as f:
        while chunk := f.read(chunk_size):
            h.update(chunk)
    return h.hexdigest()

Model fayllari yoki datasetlar yuklab olinganda ularning butunligini shu usulda tekshirishadi.

3. CSV#

CSV — eng sodda jadval formati, lekin tuzoqlari ko'p: matn ichidagi vergullar, qo'shtirnoqlar, yangi qatorlar. Hech qachon line.split(",") bilan o'qimang:

"Vali, kichik",92       # split(",") → ['"Vali', ' kichik"', '92'] ❌

Standart csv moduli bularni to'g'ri qayta ishlaydi:

import csv
 
with open("talabalar.csv", encoding="utf-8", newline="") as f:
    for row in csv.DictReader(f):            # har qator — lug'at
        print(row["ism"], int(row["ball"]))  # qiymatlar har doim SATR — o'zingiz aylantiring
 
rows = [{"ism": "Ali", "ball": 85}, {"ism": "Vali, kichik", "ball": 92}]
with open("natija.csv", "w", encoding="utf-8", newline="") as f:
    writer = csv.DictWriter(f, fieldnames=["ism", "ball"])
    writer.writeheader()
    writer.writerows(rows)

newline="" — csv moduli qator oxirlarini o'zi boshqarishi uchun (aks holda Windows'da bo'sh qatorlar paydo bo'ladi).

Amalda katta CSV'lar bilan Pandas ishlatiladi (pd.read_csv, 20-bob) — lekin kichik skriptlar va qo'shimcha bog'liqliksiz vazifalar uchun csv moduli ideal.

4. JSON#

JSON — API'lar, konfiguratsiyalar va LLM javoblarining tili.

import json
 
data = {"ism": "Aziz", "yosh": 25, "faol": True, "telefon": None, "baholar": [5, 4]}
 
s = json.dumps(data, ensure_ascii=False, indent=2)   # obyekt → satr
obj = json.loads(s)                                  # satr → obyekt
 
with open("data.json", "w", encoding="utf-8") as f:
    json.dump(data, f, ensure_ascii=False, indent=2)  # faylga
 
with open("data.json", encoding="utf-8") as f:
    obj = json.load(f)                                # fayldan

dumps/loads — satr bilan (s — string), dump/load — fayl bilan.

Python ↔ JSON tiplari#

PythonJSONIzoh
dictobjectKalitlar faqat satr bo'ladi ({1: "a"} → {"1": "a"})
list, tuplearrayTuple qaytishda list bo'lib qoladi
strstring
int, floatnumberNaN, inf — standart JSON emas!
True/Falsetrue/false
Nonenull
set, datetime, Decimal, Path, NumPy tiplari—TypeError: Object of type ... is not JSON serializable

ensure_ascii=False — o'zbek/rus harflari "а" ko'rinishida emas, o'zicha yoziladi.

Seriyalab bo'lmaydigan tiplar uchun default:

from datetime import datetime
 
json.dumps({"vaqt": datetime(2026, 10, 1)}, default=str)
# '{"vaqt": "2026-10-01 00:00:00"}'

LLM javobidan JSON ajratib olish#

Model ba'zan JSON'ni qo'shimcha matn yoki ```json bloki ichida qaytaradi. Mustahkam ajratish:

import json
import re
 
 
def extract_json(text: str) -> dict:
    """Model javobidan birinchi JSON obyektini ajratib oladi."""
    fenced = re.search(r"```(?:json)?\s*(\{.*?\})\s*```", text, re.DOTALL)
    candidate = fenced.group(1) if fenced else text[text.find("{"): text.rfind("}") + 1]
    try:
        return json.loads(candidate)
    except json.JSONDecodeError as e:
        raise ValueError(f"Javobda yaroqli JSON topilmadi: {text[:200]!r}") from e

Bu "favqulodda" usul. Yaxshiroq yo'l — API'ning structured outputs imkoniyati va Pydantic bilan validatsiya (15 va 23-boblar): model sxemaga mos JSON qaytarishga kafolat beradi.

5. JSONL — AI datasetlarining formati#

JSON Lines — har qatorda bitta JSON obyekt:

{"prompt": "Poytaxt qaysi?", "completion": "Toshkent"}
{"prompt": "2+2?", "completion": "4"}
{"prompt": "Eng uzun daryo?", "completion": "Amudaryo"}

Nega oddiy JSON massiv emas?

  • Oqim bilan o'qish: qatorma-qator — butun faylni yuklash shart emas;
  • Oxiriga qo'shish oson: "a" rejimida bitta qator yozish kifoya;
  • Buzilishga chidamli: bitta buzilgan qator butun faylni yaroqsiz qilmaydi;
  • Parallel qayta ishlash: faylni qatorlar bo'yicha bo'lish oson.

Fine-tuning datasetlari, Batch API so'rovlari, evaluation natijalari, loglar — hammasi JSONL. 7-bobdagi read_jsonl generatorini eslang. Yozish:

def append_jsonl(path: Path, record: dict) -> None:
    with open(path, "a", encoding="utf-8") as f:
        f.write(json.dumps(record, ensure_ascii=False) + "\n")

6. Pickle — qulay, lekin xavfli#

pickle deyarli har qanday Python obyektini baytlarga aylantiradi:

import pickle
 
with open("model.pkl", "wb") as f:
    pickle.dump(model, f)
 
with open("model.pkl", "rb") as f:
    model = pickle.load(f)

Boshqa cheklovlar: pickle Python versiyasi va kutubxona versiyasiga bog'liq (eski pickle yangi kod bilan ochilmasligi mumkin), boshqa tillar o'qiy olmaydi. Qoida: o'zingizning vaqtinchalik keshingiz uchun — mayli; uzoq saqlash va almashish uchun — JSON, Parquet, safetensors.

7. Boshqa formatlar — qisqa xarita#

FormatNima uchunPython'da
CSVOddiy jadvallar, Excel bilan almashishcsv, pandas.read_csv
JSONKonfiguratsiya, APIjson
JSONLDatasetlar, loglar, batch so'rovlarjson + qatorlar
ParquetKatta jadvallar: ustunli, siqilgan, tiplari saqlanadipandas.read_parquet (pyarrow)
YAMLInson yozadigan konfiguratsiya (izohlar bilan)pyyaml — yaml.safe_load!
TOMLKonfiguratsiya (pyproject.toml)tomllib (standart, faqat o'qish)
safetensorsModel og'irliklari (xavfsiz)safetensors
NPY/NPZNumPy massivlarinp.save, np.load
SQLiteKichik ma'lumotlar bazasi bitta fayldasqlite3 (standart)

Parquet haqida alohida: 1 GB CSV ko'pincha 100–200 MB Parquet'ga aylanadi, 5–20 baravar tez o'qiladi va ustun tiplarini (sana, butun son, kategoriya) saqlaydi. Katta datasetlar uchun standart.

import tomllib
 
with open("pyproject.toml", "rb") as f:     # tomllib binary rejim talab qiladi
    cfg = tomllib.load(f)
print(cfg["project"]["name"])

8. Xavfsiz yozish: atomic write#

Tasavvur qiling: 3 soatlik hisob-kitob natijasini results.jsonga yozyapsiz va yozish o'rtasida dastur yiqildi (xotira tugadi, Ctrl+C, server o'chdi). Natija: yarim yozilgan, buzilgan fayl — va eski natija ham yo'q.

Yechim — avval vaqtinchalik faylga yozib, keyin bir amalda almashtirish:

import json
import os
import tempfile
from pathlib import Path
 
 
def atomic_write_json(path: Path, data) -> None:
    path.parent.mkdir(parents=True, exist_ok=True)
    fd, tmp = tempfile.mkstemp(dir=path.parent, prefix=f".{path.name}.", suffix=".tmp")
    try:
        with os.fdopen(fd, "w", encoding="utf-8") as f:
            json.dump(data, f, ensure_ascii=False, indent=2)
            f.flush()
            os.fsync(f.fileno())          # diskka haqiqatan yozilganiga ishonch
        os.replace(tmp, path)             # atomik: yo eski fayl, yo yangi — oraliq holat yo'q
    except BaseException:
        Path(tmp).unlink(missing_ok=True)
        raise

os.replace bitta fayl tizimi ichida atomik — o'quvchi hech qachon yarim fayl ko'rmaydi. Checkpoint'lar, kesh fayllari va natijalar uchun shu naqshdan foydalaning.

9. shutil, tempfile va boshqa yordamchilar#

import shutil
import tempfile
 
shutil.copy2("a.csv", "backup/a.csv")         # nusxa (metama'lumot bilan)
shutil.copytree("data", "data_backup")        # butun papka
shutil.rmtree("tmp_outputs")                  # papkani butunlay o'chirish — EHTIYOT!
shutil.move("a.csv", "archive/")
shutil.make_archive("results", "zip", "outputs")   # outputs/ → results.zip
shutil.disk_usage("/").free                   # bo'sh joy
 
with tempfile.TemporaryDirectory() as tmp:    # blokdan chiqqanda o'chiriladi
    work = Path(tmp) / "work.txt"
    work.write_text("vaqtinchalik", encoding="utf-8")

TemporaryDirectory testlarda juda foydali (16-bobda pytest'ning tmp_path fixture'i bilan buni yanada osonroq qilamiz).

10. Amaliyot: dataset tayyorlash skripti#

CSV'dan sharhlarni o'qib, tozalab, train/val'ga bo'lib, JSONL sifatida saqlaydigan to'liq skript:

"""reviews.csv → train.jsonl + val.jsonl"""
 
import csv
import json
import logging
import random
from pathlib import Path
 
log = logging.getLogger(__name__)
 
ROOT = Path(__file__).resolve().parent
RAW = ROOT / "data" / "raw" / "reviews.csv"
OUT = ROOT / "data" / "processed"
VALID_LABELS = {"positive", "negative", "neutral"}
 
 
def read_reviews(path: Path):
    with open(path, encoding="utf-8-sig", newline="") as f:
        for n, row in enumerate(csv.DictReader(f), start=2):     # 1-qator — sarlavha
            text = (row.get("text") or "").strip()
            label = (row.get("label") or "").strip().lower()
            if not text or label not in VALID_LABELS:
                log.warning("%s:%d o'tkazib yuborildi (text=%r, label=%r)", path.name, n, text[:30], label)
                continue
            yield {"text": " ".join(text.split()), "label": label}
 
 
def write_jsonl(path: Path, records: list[dict]) -> None:
    path.parent.mkdir(parents=True, exist_ok=True)
    with open(path, "w", encoding="utf-8") as f:
        for r in records:
            f.write(json.dumps(r, ensure_ascii=False) + "\n")
 
 
def main(val_ratio: float = 0.1, seed: int = 42) -> None:
    logging.basicConfig(level=logging.INFO, format="%(levelname)s %(message)s")
    records = list(read_reviews(RAW))
    unique = list({r["text"]: r for r in records}.values())        # dublikat matnlarni olib tashlash
    log.info("%d ta yozuv, %d ta dublikat olib tashlandi", len(unique), len(records) - len(unique))
 
    random.Random(seed).shuffle(unique)
    n_val = max(1, int(len(unique) * val_ratio))
    write_jsonl(OUT / "val.jsonl", unique[:n_val])
    write_jsonl(OUT / "train.jsonl", unique[n_val:])
    log.info("train=%d, val=%d → %s", len(unique) - n_val, n_val, OUT)
 
 
if __name__ == "__main__":
    main()

Bu skriptda bobning deyarli hamma g'oyasi bor: __file__ga nisbatan yo'llar, utf-8-sig (Excel CSV), csv.DictReader, generator bilan o'qish, buzilgan qatorlarni logga yozish, dublikatlarni lug'at orqali olib tashlash, seed bilan takrorlanuvchan aralashtirish, JSONL yozish.

Nima noto'g'ri ketishi mumkin#

BelgiSababYechim
Buzilgan o'zbek/rus harflari, UnicodeDecodeErrorencoding ko'rsatilmaganencoding="utf-8" (Excel CSV: utf-8-sig)
Birinchi ustun nomi nameBOMencoding="utf-8-sig"
FileNotFoundError, garchi fayl bor bo'lsa hamJoriy papka boshqaPath(__file__).parent ga nisbatan yo'l
Fayl bo'shab qoldi"w" rejimida ochildi"a" yoki "x"; atomik yozish
MemoryError katta fayldaread() / readlines()for line in f
CSV'da ustunlar siljigansplit(",")csv moduli yoki Pandas
Windows'da CSV'da bo'sh qatorlarnewline="" yo'qopen(..., newline="")
Object of type float32 is not JSON serializableNumPy tipifloat(x) yoki x.item()
Har ishga tushirishda boshqa natijaglob tartibisorted(glob(...))
Yuklangan .pkl ochildi va...pickle kod bajaradiIshonchsiz pickle'ni ochmang; safetensors/JSON
Amaliy topshiriq

1. Papka statistikasi

folder_report(root) funksiyasini yozing: papkadagi barcha fayllarni (ichki papkalar bilan) ko'rib, kengaytmalar bo'yicha soni va umumiy hajmini (MB'da, 2 xona kasr bilan) jadval qilib chiqarsin, eng katta 5 faylni ko'rsatsin.

Maslahatni ko'rsatish

Counter(p.suffix.lower() for p in root.rglob('*') if p.is_file()); hajm uchun sum(p.stat().st_size ...).

Amaliy topshiriq

2. CSV → JSONL konvertor

CSV faylni JSONL'ga aylantiruvchi CLI skript yozing (python convert.py input.csv output.jsonl): sonli ko'rinadigan qiymatlarni int/floatga aylantirsin, bo'sh qiymatlarni null qilsin, yozilgan qatorlar sonini chiqarsin. sys.argv ishlating (18-bobda argparseni ko'ramiz).

Maslahatni ko'rsatish

csv.DictReader + json.dumps(row, ensure_ascii=False); sonli ustunlar uchun 10-bobdagi safe_float.

Amaliy topshiriq

3. Natijalar jurnali

ML tajribalari jurnalini yozing: log_run(params: dict, metrics: dict) runs.jsonlga vaqt belgisi bilan qator qo'shsin (NumPy sonlari ham to'g'ri yozilsin), best_run(metric) esa eng yaxshi tajribani qaytarsin.

Maslahatni ko'rsatish

Har bir tajriba — bitta JSONL qator (append). O'qishda max(records, key=lambda r: r['metrics']['acc']).

Amaliy topshiriq

4. Atomik yozishni sinash

atomic_write_json va oddiy json.dumpni solishtiring: yozish o'rtasida xato ko'taradigan "yomon" obyekt yarating (masalan, default funksiyasi uchinchi chaqiruvda RuntimeError ko'tarsin). Har ikki holatda ham avvalgi fayl mazmuniga nima bo'lishini tekshiring.

Yodda saqlang
  • 01pathlib.Path: / bilan birlashtirish, name/stem/suffix/parent, mkdir(parents=True, exist_ok=True), glob/rglob (saralang!).
  • 02Yo'llarni Path(__file__) ga nisbatan quring — joriy papkaga bog'liq bo'lmasin.
  • 03open: har doim with va encoding='utf-8'; 'w' faylni darhol bo'shatadi; katta fayllarni qatorma-qator o'qing.
  • 04CSV — csv moduli (split emas), newline=''; JSON — dump/load, ensure_ascii=False, NumPy tiplarini aylantiring.
  • 05JSONL — AI datasetlari va loglar uchun standart: oqim, qo'shish, buzilishga chidamlilik.
  • 06pickle va yaml.load ishonchsiz manbadan — kod bajarilishi xavfi.
  • 07Muhim fayllarni atomik yozing: vaqtinchalik fayl + os.replace.

Mustahkamlash

Test va amaliy masalalar

Avval testni ishlang — har javobdan keyin izoh chiqadi. Keyin masalalarni shu yerning o'zida yechib, brauzerdagi haqiqiy Python bilan avtomatik tekshiring. Natijalaringiz kurs progressi sahifasida jamlanadi.

Test: topshirilmaganMasalalar: 0/3

Bilimni tekshirish

Bob bo'yicha test

12 ta savol · har javobdan keyin to'g'ri yoki xatoligi va izoh ko'rsatiladi · oxirida natija foizda.

Amaliy masalalar

Kodni yozing va «Tekshirish»ni bosing (yoki Ctrl/⌘ + Enter). Kodingiz shu brauzerda saqlanib turadi.

01JSONL yozish va o'qish

write_jsonl(path, records) — har yozuvni bitta qatorga (ensure_ascii=False) yozib, yozilganlar sonini qaytarsin. read_jsonl(path) — generator: bo'sh qatorlarni o'tkazib, buzilgan qatorlarni (JSON emas) ham o'tkazib, lug'atlarni chiqarsin.

02CSV'dan statistika

price_stats(csv_text) — name,city,price ustunli CSV matnidan (io.StringIO + csv.DictReader) har shahar uchun o'rtacha narxni lug'at qilib qaytarsin (2 xona yaxlitlab). Narxi bo'sh yoki son bo'lmagan qatorlar e'tiborsiz.

03Atomik yozish

atomic_write_text(path, text) — matnni avval shu papkadagi vaqtinchalik faylga yozib, keyin os.replace bilan almashtirsin. Xato bo'lsa vaqtinchalik fayl o'chirilsin. Funksiya pathlib.Path qabul qiladi.