Fayllar va formatlar: pathlib, JSON, CSV, SQLite
pathlib: yo'llar bilan ishlash
Eski usul — yo'llarni matn sifatida qo'shish. U platformaga bog'liq va xatolarga moyil.
import os from pathlib import Path eski = os.path.join("malumot", "2026", "hisobot.csv") yangi = Path("malumot") / "2026" / "hisobot.csv" print("os.path.join:", eski) print("pathlib :", yangi) p = Path("/uy/talaba/malumot/hisobot.2026.csv") print("\nqismlari:") for nom, qiymat in [("nomi", p.name), ("kengaytma", p.suffix), ("hamma kengaytmalar", p.suffixes), ("kengaytmasiz", p.stem), ("papka", p.parent), ("ildiz", p.parts[:2])]: print(f" {nom:20} {qiymat}")
os.path.join: malumot/2026/hisobot.csv
pathlib : malumot/2026/hisobot.csv
qismlari:
nomi hisobot.2026.csv
kengaytma .csv
hamma kengaytmalar ['.2026', '.csv']
kengaytmasiz hisobot.2026
papka /uy/talaba/malumot
ildiz ('/', 'uy')
Foydali amallar:
from pathlib import Path import tempfile papka = Path(tempfile.mkdtemp()) (papka / "ichki").mkdir(parents=True, exist_ok=True) (papka / "a.csv").write_text("ism,baho\nAziz,85\n", encoding="utf-8") (papka / "b.csv").write_text("ism,baho\nBobur,90\n", encoding="utf-8") (papka / "ichki" / "c.csv").write_text("ism,baho\nDilnoza,70\n", encoding="utf-8") (papka / "eslatma.txt").write_text("bu CSV emas", encoding="utf-8") print("faqat shu papkadagi CSV lar:", sorted(p.name for p in papka.glob("*.csv"))) print("ichkilari bilan birga :", sorted(str(p.relative_to(papka)) for p in papka.rglob("*.csv"))) print("\nbor-yo'qligi:", (papka / "a.csv").exists(), "| papkami:", (papka / "ichki").is_dir()) print("hajmi:", (papka / "a.csv").stat().st_size, "bayt") print("\no'qish bir qatorda:", (papka / "a.csv").read_text(encoding="utf-8").strip()) import shutil; shutil.rmtree(papka)
faqat shu papkadagi CSV lar: ['a.csv', 'b.csv'] ichkilari bilan birga : ['a.csv', 'b.csv', 'ichki/c.csv'] bor-yo'qligi: True | papkami: True hajmi: 17 bayt o'qish bir qatorda: ism,baho Aziz,85
| Amal | pathlib |
|---|---|
| Birlashtirish | Path("a") / "b" / "c.txt" |
| O'qish / yozish | p.read_text(encoding="utf-8"), p.write_text(...) |
| Papka yaratish | p.mkdir(parents=True, exist_ok=True) |
| Qidirish | p.glob("*.csv"), p.rglob("*.csv") (ichkilari bilan) |
| Mavjudlik | p.exists(), p.is_file(), p.is_dir() |
| Kengaytmani almashtirish | p.with_suffix(".json") |
:::gotcha encoding ni har doim yozing
open(yol) va read_text() kodlashni tizimdan oladi. Windows da u ko'pincha cp1251, Linux da
utf-8. Ya'ni bir xil kod ikki kompyuterda turli natija beradi. Har doim
encoding="utf-8" yozing — bu eng ko'p uchraydigan "menda ishlaydi" xatolaridan biri.
:::
Buni ko'rsatamiz:
import tempfile, os from pathlib import Path p = Path(tempfile.mkdtemp()) / "uzbek.txt" p.write_text("O'zbekiston — Toshkent shahri\n", encoding="utf-8") print("utf-8 bilan :", repr(p.read_text(encoding="utf-8").strip())) try: print("latin-1 bilan :", repr(p.read_text(encoding="latin-1").strip())) except UnicodeDecodeError as e: print("latin-1 bilan : XATO -", e) import shutil; shutil.rmtree(p.parent)
utf-8 bilan : "O'zbekiston — Toshkent shahri" latin-1 bilan : "O'zbekiston â\x80\x94 Toshkent shahri"
latin-1 xato bermadi — u har qanday baytni "o'qiy oladi", lekin natija buzuq. Bu eng xavfli
holat: xato yo'q, ma'lumot esa noto'g'ri.
JSON: tuzilgan ma'lumot
shu faylni yaratingsrc/hisobot/chiqarish.py
"""Natijani turli formatlarda yozish.""" import csv import json import logging from pathlib import Path from typing import Any from .hisob import daraja_taqsimoti, guruh_ortachasi from .modellar import Natija log = logging.getLogger(__name__) def xulosa(natija: Natija) -> dict[str, Any]: """Natijadan JSON ga yaroqli lug'at yasaydi.""" return { "jami": natija.jami, "togri": len(natija.talabalar), "xato": len(natija.xatolar), "guruh_ortachasi": guruh_ortachasi(natija.talabalar), "darajalar": daraja_taqsimoti(natija.talabalar), "xatolar": [{"qator": q, "ism": i, "sabab": s} for q, i, s in natija.xatolar], } def json_yoz(natija: Natija, yol: str | Path) -> None: p = Path(yol) p.write_text(json.dumps(xulosa(natija), ensure_ascii=False, indent=2), encoding="utf-8") log.info("JSON yozildi: %s", p) def csv_yoz(natija: Natija, yol: str | Path) -> None: p = Path(yol) with p.open("w", encoding="utf-8", newline="") as f: yozuvchi = csv.DictWriter(f, fieldnames=["ism", "guruh", "baho", "sana", "daraja"]) yozuvchi.writeheader() for t in natija.talabalar: yozuvchi.writerow({"ism": t.ism, "guruh": t.guruh, "baho": t.baho, "sana": t.sana, "daraja": t.daraja.value}) log.info("CSV yozildi: %s", p)
.venv/bin/python3 -c " from hisobot.oqish import oqi, tozala from hisobot.chiqarish import json_yoz, csv_yoz n = tozala(oqi('sinov_malumot.csv')) json_yoz(n, 'natija.json') csv_yoz(n, 'natija.csv') " cat natija.json echo "--- CSV ---" cat natija.csv
{
"jami": 8,
"togri": 6,
"xato": 2,
"guruh_ortachasi": {
"A": 90.67,
"B": 83.0,
"C": 61.0
},
"darajalar": {
"yaxshi": 3,
"a'lo": 2,
"qoniqarli": 1
},
"xatolar": [
{
"qator": 5,
"ism": "Elyor",
"sabab": "baho son emas: ''"
},
{
"qator": 8,
"ism": "Hasan",
"sabab": "baho son emas: 'abc'"
}
]
}--- CSV ---
ism,guruh,baho,sana,daraja
Aziz,A,85,2026-09-01,yaxshi
Bobur,A,92,2026-09-01,a'lo
Dilnoza,B,78,2026-09-02,yaxshi
Feruza,A,95,2026-09-03,a'lo
Gulnora,C,61,2026-09-03,qoniqarli
Iroda,B,88,2026-09-04,yaxshi
8 qatordan 2 tasi rad etildi
ensure_ascii=False muhim: usiz o'zbekcha harflar ʻ kabi ko'rinadi. Tekshiramiz:
import json malumot = {"ism": "Feruza", "daraja": "a'lo", "izoh": "o'qishni tugatdi"} print("ensure_ascii=True (sukut):", json.dumps(malumot)) print("ensure_ascii=False :", json.dumps(malumot, ensure_ascii=False))
ensure_ascii=True (sukut): {"ism": "Feruza", "daraja": "a'lo", "izoh": "o'qishni tugatdi"}
ensure_ascii=False : {"ism": "Feruza", "daraja": "a'lo", "izoh": "o'qishni tugatdi"}
Ikkalasi ham to'g'ri JSON, lekin ikkinchisi odam o'qiy oladigan.
JSON nimani saqlay olmaydi
import json from datetime import date, datetime from decimal import Decimal sinovlar = [ ("matn", "salom"), ("son", 42), ("kasr", 3.14), ("mantiqiy", True), ("yo'q", None), ("ro'yxat", [1, 2]), ("lug'at", {"a": 1}), ("sana", date(2026, 9, 1)), ("to'plam", {1, 2, 3}), ("Decimal", Decimal("10.5")), ("kortej", (1, 2)), ] for nom, qiymat in sinovlar: try: natija = json.dumps(qiymat) print(f" {nom:10} -> {natija}") except TypeError as e: print(f" {nom:10} -> XATO: {e}")
matn -> "salom"
son -> 42
kasr -> 3.14
mantiqiy -> true
yo'q -> null
ro'yxat -> [1, 2]
lug'at -> {"a": 1}
sana -> XATO: Object of type date is not JSON serializable
to'plam -> XATO: Object of type set is not JSON serializable
Decimal -> XATO: Object of type Decimal is not JSON serializable
kortej -> [1, 2]
tuple ro'yxatga aylandi (qaytarib olib bo'lmaydi), date, set va Decimal esa umuman
yozilmadi. Yechim — default funksiyasi:
import json from datetime import date, datetime from decimal import Decimal def aylantir(x): if isinstance(x, (date, datetime)): return x.isoformat() if isinstance(x, set): return sorted(x) if isinstance(x, Decimal): return str(x) raise TypeError(f"JSON ga aylantirib bo'lmaydi: {type(x).__name__}") malumot = {"sana": date(2026, 9, 1), "guruhlar": {"B", "A"}, "narx": Decimal("10.50")} print(json.dumps(malumot, default=aylantir, ensure_ascii=False))
{"sana": "2026-09-01", "guruhlar": ["A", "B"], "narx": "10.50"}
CSV tuzoqlari
import csv, io xom = 'ism,izoh,baho\nAziz,"yaxshi, lekin kech topshirdi",85\nBobur,"u ""ajoyib"" dedi",90\n' print("xom matn:") print(xom) print("csv moduli bilan o'qilgani:") for q in csv.DictReader(io.StringIO(xom)): print(" ", q) print("\nqo'lda split(',') bilan (XATO):") for qator in xom.strip().splitlines()[1:]: print(" ", qator.split(","))
xom matn:
ism,izoh,baho
Aziz,"yaxshi, lekin kech topshirdi",85
Bobur,"u ""ajoyib"" dedi",90
csv moduli bilan o'qilgani:
{'ism': 'Aziz', 'izoh': 'yaxshi, lekin kech topshirdi', 'baho': '85'}
{'ism': 'Bobur', 'izoh': 'u "ajoyib" dedi', 'baho': '90'}
qo'lda split(',') bilan (XATO):
['Aziz', '"yaxshi', ' lekin kech topshirdi"', '85']
['Bobur', '"u ""ajoyib"" dedi"', '90']
split(",") vergulli matnni buzdi. CSV ni hech qachon qo'lda tahlil qilmang — csv moduli
qo'shtirnoq, ichki vergul va ko'chirilgan qo'shtirnoqni to'g'ri hal qiladi.
Yozishda ham bitta tuzoq bor:
import csv, io, tempfile, os from pathlib import Path papka = Path(tempfile.mkdtemp()) for nom, newline in [("newline_yoq.csv", None), ("newline_bor.csv", "")]: with open(papka / nom, "w", encoding="utf-8", newline=newline) as f: w = csv.writer(f) w.writerow(["ism", "baho"]) w.writerow(["Aziz", 85]) xom = (papka / nom).read_bytes() print(f"{nom:18} bayt: {xom!r}") import shutil; shutil.rmtree(papka)
newline_yoq.csv bayt: b'ism,baho\r\nAziz,85\r\n' newline_bor.csv bayt: b'ism,baho\r\nAziz,85\r\n'
Linux da farq yo'q, Windows da esa newline=None har qatordan keyin bo'sh qator qo'shadi.
Shuning uchun csv bilan yozganda har doim newline="" yozing.
SQLite: fayl ichidagi ma'lumotlar bazasi
CSV kichik ma'lumot uchun. Ma'lumot o'sganda va so'rov kerak bo'lganda SQLite ishlatiladi — u standart kutubxonada, server talab qilmaydi.
import sqlite3, tempfile, time from pathlib import Path yol = Path(tempfile.mkdtemp()) / "talabalar.db" con = sqlite3.connect(yol) con.execute(""" CREATE TABLE talaba ( id INTEGER PRIMARY KEY, ism TEXT NOT NULL, guruh TEXT NOT NULL, baho INTEGER NOT NULL CHECK (baho BETWEEN 0 AND 100) ) """) qatorlar = [(f"Talaba{i}", "ABC"[i % 3], 50 + (i * 7) % 51) for i in range(10_000)] t0 = time.perf_counter() con.executemany("INSERT INTO talaba (ism, guruh, baho) VALUES (?, ?, ?)", qatorlar) con.commit() yozish_ms = (time.perf_counter() - t0) * 1000 t0 = time.perf_counter() natija = con.execute( "SELECT guruh, COUNT(*), ROUND(AVG(baho), 2) FROM talaba GROUP BY guruh ORDER BY guruh" ).fetchall() soro_ms = (time.perf_counter() - t0) * 1000 print(f"10 000 qator yozildi: {yozish_ms:.0f} ms | fayl hajmi: {yol.stat().st_size // 1024} KB") print(f"guruh bo'yicha so'rov: {soro_ms:.1f} ms") for guruh, soni, ortacha in natija: print(f" {guruh}: {soni} talaba, o'rtacha {ortacha}") con.close() import shutil; shutil.rmtree(yol.parent)
10 000 qator yozildi: 17 ms | fayl hajmi: 224 KB guruh bo'yicha so'rov: 1.4 ms A: 3334 talaba, o'rtacha 73.99 B: 3333 talaba, o'rtacha 74.99 C: 3333 talaba, o'rtacha 76.0
CHECK cheklovi muhim: baza noto'g'ri ma'lumotni qabul qilmaydi. Bu tekshiruvning oxirgi
chizig'i:
import sqlite3 con = sqlite3.connect(":memory:") con.execute("CREATE TABLE t (baho INTEGER CHECK (baho BETWEEN 0 AND 100))") for qiymat in (85, 150): try: con.execute("INSERT INTO t VALUES (?)", (qiymat,)) print(f" {qiymat}: qabul qilindi") except sqlite3.IntegrityError as e: print(f" {qiymat}: rad etildi — {e}") con.close()
85: qabul qilindi 150: rad etildi — CHECK constraint failed: baho BETWEEN 0 AND 100
:::gotcha SQL ni matn qo'shib yasamang
f"SELECT * FROM t WHERE ism = '{ism}'" — bu SQL injection. Foydalanuvchi ' OR 1=1 --
yozsa, butun jadvalni ko'radi. Har doim ? parametrini ishlating: execute("... WHERE ism = ?", (ism,)).
:::
import sqlite3 con = sqlite3.connect(":memory:") con.execute("CREATE TABLE t (ism TEXT, sir TEXT)") con.executemany("INSERT INTO t VALUES (?, ?)", [("Aziz", "maxfiy1"), ("Bobur", "maxfiy2")]) xavfli_kirish = "' OR '1'='1" print("1) Matn qo'shish bilan (XAVFLI):") soro = f"SELECT * FROM t WHERE ism = '{xavfli_kirish}'" print(" so'rov:", soro) print(" natija:", con.execute(soro).fetchall()) print("\n2) Parametr bilan (XAVFSIZ):") print(" natija:", con.execute("SELECT * FROM t WHERE ism = ?", (xavfli_kirish,)).fetchall()) con.close()
1) Matn qo'shish bilan (XAVFLI):
so'rov: SELECT * FROM t WHERE ism = '' OR '1'='1'
natija: [('Aziz', 'maxfiy1'), ('Bobur', 'maxfiy2')]
2) Parametr bilan (XAVFSIZ):
natija: []
Birinchi so'rov hamma qatorni qaytardi. Ikkinchisi hech narsa — chunki bunday ismli talaba yo'q.
Formatlarni solishtiramiz
import csv, json, sqlite3, tempfile, time from pathlib import Path papka = Path(tempfile.mkdtemp()) malumot = [{"ism": f"Talaba{i}", "guruh": "ABC"[i % 3], "baho": 50 + (i * 7) % 51} for i in range(20_000)] # CSV t0 = time.perf_counter() with (papka / "d.csv").open("w", encoding="utf-8", newline="") as f: w = csv.DictWriter(f, fieldnames=["ism", "guruh", "baho"]); w.writeheader(); w.writerows(malumot) csv_yoz = (time.perf_counter() - t0) * 1000 # JSON t0 = time.perf_counter() (papka / "d.json").write_text(json.dumps(malumot, ensure_ascii=False), encoding="utf-8") json_yoz = (time.perf_counter() - t0) * 1000 # SQLite t0 = time.perf_counter() con = sqlite3.connect(papka / "d.db") con.execute("CREATE TABLE t (ism TEXT, guruh TEXT, baho INTEGER)") con.executemany("INSERT INTO t VALUES (:ism, :guruh, :baho)", malumot) con.commit(); con.close() db_yoz = (time.perf_counter() - t0) * 1000 import pandas as pd show(pd.DataFrame([ {"format": "CSV", "yozish, ms": round(csv_yoz), "hajm, KB": (papka / "d.csv").stat().st_size // 1024, "tuzilma": "tekis jadval", "so'rov": "yo'q — hammasini o'qish kerak"}, {"format": "JSON", "yozish, ms": round(json_yoz), "hajm, KB": (papka / "d.json").stat().st_size // 1024, "tuzilma": "ichma-ich", "so'rov": "yo'q — hammasini o'qish kerak"}, {"format": "SQLite", "yozish, ms": round(db_yoz), "hajm, KB": (papka / "d.db").stat().st_size // 1024, "tuzilma": "jadvallar + indeks", "so'rov": "SQL, indeks bilan tez"}, ])) import shutil; shutil.rmtree(papka)
| format | yozish, ms | hajm, KB | tuzilma | so'rov |
|---|---|---|---|---|
| CSV | 11 | 341 | tekis jadval | yo'q — hammasini o'qish kerak |
| JSON | 8 | 966 | ichma-ich | yo'q — hammasini o'qish kerak |
| SQLite | 38 | 436 | jadvallar + indeks | SQL, indeks bilan tez |
Qaysi birini tanlash:
| Holat | Format |
|---|---|
| Excel da ochiladi, odam tahrirlaydi | CSV |
| Tuzilishi ichma-ich, API bilan almashinuv | JSON |
| Qator ko'p, qidirish/filtrlash kerak | SQLite |
| Juda katta, ustun bo'yicha tahlil | Parquet (pandas, pyarrow) |
Testlar
shu faylni yaratingtests/test_chiqarish.py
import json from hisobot.chiqarish import csv_yoz, json_yoz, xulosa def test_xulosa_tuzilishi(talabalar): from hisobot.modellar import Natija x = xulosa(Natija(talabalar=talabalar, xatolar=[(5, "X", "baho son emas")])) assert x["jami"] == 4 assert x["togri"] == 3 assert x["xato"] == 1 assert x["guruh_ortachasi"] == {"A": 90.0, "B": 70.0} assert x["xatolar"][0]["qator"] == 5 def test_json_yoz_oqiladi(tmp_path, talabalar): from hisobot.modellar import Natija yol = tmp_path / "n.json" json_yoz(Natija(talabalar=talabalar), yol) qayta = json.loads(yol.read_text(encoding="utf-8")) assert qayta["togri"] == 3 def test_json_uzbekcha_harflar(tmp_path): from hisobot.modellar import Natija, Talaba yol = tmp_path / "n.json" json_yoz(Natija(talabalar=[Talaba("Feruza", "A", 95, "2026-09-01")]), yol) matn = yol.read_text(encoding="utf-8") assert "a'lo" in matn assert "\\u" not in matn def test_csv_yoz_sarlavha(tmp_path, talabalar): from hisobot.modellar import Natija yol = tmp_path / "n.csv" csv_yoz(Natija(talabalar=talabalar), yol) qatorlar = yol.read_text(encoding="utf-8").splitlines() assert qatorlar[0] == "ism,guruh,baho,sana,daraja" assert len(qatorlar) == 4
.venv/bin/python3 -m pytest -q python3 -m mypy
..............F........................... [100%]
=================================== FAILURES ===================================
________________________________ test_fayl_yoq _________________________________
tmp_path = PosixPath('/tmp/pytest-of-abulqosim/pytest-57/test_fayl_yoq0')
def test_fayl_yoq(tmp_path):
with pytest.raises(FileNotFoundError):
> oqi(tmp_path / "yoq.csv")
tests/test_oqish.py:29:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
yol = PosixPath('/tmp/pytest-of-abulqosim/pytest-57/test_fayl_yoq0/yoq.csv')
def oqi(yol: str | Path) -> list[dict[str, str]]:
"""CSV ni o'qiydi. Har qanday muammoda FaylXato qaytaradi."""
p = Path(yol)
log.debug("fayl o'qilmoqda: %s", p)
try:
matn = p.read_text(encoding="utf-8")
except FileNotFoundError:
> raise FaylXato(str(p), "fayl topilmadi") from None
E hisobot.xatolar.FaylXato: faylni o'qib bo'lmadi: /tmp/pytest-of-abulqosim/pytest-57/test_fayl_yoq0/yoq.csv (fayl topilmadi)
src/hisobot/oqish.py:22: FaylXato
=========================== short test summary info ============================
FAILED tests/test_oqish.py::test_fayl_yoq - hisobot.xatolar.FaylXato: faylni ...
Success: no issues found in 8 source files
Xulosa
| Tushuncha | Asosiy fikr |
|---|---|
pathlib |
/ bilan birlashtiring; read_text, glob, rglob |
encoding="utf-8" |
Har doim yozing — usiz kod platformaga bog'liq bo'ladi |
latin-1 |
Xato bermaydi, lekin ma'lumotni buzadi — eng xavfli holat |
ensure_ascii=False |
O'zbekcha harflar o'qiladigan bo'lib qoladi |
| JSON cheklovi | date, set, Decimal yozilmaydi; tuple ro'yxatga aylanadi |
| CSV | Qo'lda split(",") qilmang; yozishda newline="" |
| SQLite | Standart kutubxonada; CHECK bilan cheklov qo'ying |
| SQL parametrlari | ? ishlating — matn qo'shish injection ga olib keladi |
Talaba ishi
json_yozgadateobyekti tushsa nima bo'ladi?default=bilan tuzating.- 100 000 qatorli CSV yasang va uni
csv.DictReaderhamdapandas.read_csvbilan o'qib vaqtni solishtiring. Farq qancha? - SQLite jadvaliga
CREATE INDEXqo'shing vaWHERE guruh = 'A'so'rovini indekssiz va indeks bilan o'lchang. xulosa()natijasini Parquet ga yozib ko'ring (pandas+pyarrow). Hajm CSV dan qanday farq qiladi?
Bu bobni bepul o'qidingiz.
Kitob o'rgatadi, lekin sizning kodingiz nega ishlamaganini ayta olmaydi. Kursda uy vazifangiz tekshiriladi.