अध्याय 25

JSON और CSV

csv मॉड्यूल से कोट्स वाली टेबल पढ़ना और लिखना, newline="" की आवश्यकता, json से संरचित डेटा रखना, और कौन से प्रकार रास्ते में बदल जाते हैं।

34 मिनटPython 3.12
  1. 1समस्या
  2. 2समझें
  3. 3उदाहरण
  4. 4अनुमान
  5. 5स्वयं करें
  6. 6चुनौती

वह समस्या जिसे हम हल कर रहे हैं

अध्याय तेईस से हम .split(",") के साथ फ़ाइलों को विभाजित करते आ रहे हैं, और यह काम करता था। अब एक ऐसी फ़ाइल पर विचार करें जहाँ किसी फ़ील्ड के अंदर ही एक अल्पविराम (comma) है:

text
name,note,price
pen,blue ink,15.0
bag,"large, sturdy",850.0
python
with open("items.csv", "r", encoding="utf-8") as fh:
    for line in fh:
        print(line.strip().split(","))
text
['name', 'note', 'price']
['pen', 'blue ink', '15.0']
['bag', '"large', ' sturdy"', '850.0']

अंतिम पंक्ति तीन के बजाय चार फ़ील्ड के साथ निकली, और उद्धरण चिह्न डेटा का हिस्सा बन गए।

उद्धरण चिह्न कोई गलती नहीं है — यह सीएसवी का नियम है, और यह ठीक इसी स्थिति के लिए मौजूद है। गलती हमारे पढ़ने के तरीके में है।

यह काम पहले से ही किया जा चुका है:

python
import csv

with open("items.csv", "r", encoding="utf-8", newline="") as fh:
    for row in csv.reader(fh):
        print(row)
text
['name', 'note', 'price']
['pen', 'blue ink', '15.0']
['bag', 'large, sturdy', '850.0']

यह अध्याय दो प्रारूपों के बारे में है — तालिकाओं के लिए CSV, संरचना के लिए JSON — और दोनों के लिए मॉड्यूल पायथन के साथ आते हैं।

इस मिशन के अंत तक आप सीखेंगे

  • csv.reader और csv.DictReader से पढ़ना, और csv.writer से लिखना
  • यह समझना कि newline="" क्यों लिखा जाता है
  • json.dumps/loads और json.dump/load के बीच अंतर बताना
  • यह जानना कि कौन से पायथन प्रकार JSON से वापस आते हैं और कौन से नहीं
  • CSV और JSON के बीच सही चुनाव करना
  • JSONDecodeError को पढ़ना और समस्या खोजना

पूर्वापेक्षाएँ: एक्सेप्शन्स — टूटी हुई स्थिति को संभालना.


CSV पढ़ना

csv.DictReader पहली पंक्ति को हेडर मानता है और प्रत्येक पंक्ति को एक डिक्शनरी बनाता है:

python
import csv

with open("items.csv", "r", encoding="utf-8", newline="") as fh:
    for row in csv.DictReader(fh):
        print(row["name"], "-", row["price"], type(row["price"]))
text
pen - 15.0 <class 'str'>
bag - 850.0 <class 'str'>

दो बातें:

पहुँच नाम द्वारा होती है, इसलिए कॉलमों का क्रम बदलने से कोड नहीं टूटता। DictReader लगभग हमेशा बेहतर विकल्प होता है।

लेकिन price अभी भी टेक्स्ट है। csv मॉड्यूल केवल फ़ील्ड्स को अलग करता है, उन्हें परिवर्तित नहीं करता।

CSV लिखना

डिक्शनरी की एक सूची के लिए, DictWriter:

python
import csv

rows = [
    {"name": "pen", "price": 15.0},
    {"name": "bag", "price": 850.0},
]

with open("out.csv", "w", encoding="utf-8", newline="") as fh:
    writer = csv.DictWriter(fh, fieldnames=["name", "price"])
    writer.writeheader()
    writer.writerows(rows)
text
name,price
pen,15.0
bag,850.0
newline="" क्यों? csv मॉड्यूल स्वयं तय करता है कि पंक्ति का अंत क्या है। newline="" कुछ प्रणालियों पर हर पंक्ति के बाद खाली पंक्ति आने से रोकता है।

JSON — ऐसी संरचना जो एक तालिका में नहीं समा सकती

CSV एक तालिका है: पंक्तियाँ और कॉलम, सब कुछ समतल (flat)। लेकिन क्या होगा यदि किसी ऑर्डर में आइटमों की एक सूची हो, और प्रत्येक आइटम में टैग्स की एक सूची हो? एक तालिका उसे नहीं संभाल सकती।

python
import json

order = {"name": "pen", "price": 15.0, "tags": ["ink", "blue"], "stocked": True, "note": None}

print(json.dumps(order))
text
{"name": "pen", "price": 15.0, "tags": ["ink", "blue"], "stocked": true, "note": null}

json.dumps पायथन ऑब्जेक्ट को टेक्स्ट में बदलता है। ध्यान दें: True बन गया true और None बन गया null।

पठनीय बनाने के लिए indent=2:

python
import json

order = {"name": "pen", "tags": ["ink", "blue"]}

print(json.dumps(order, indent=2))
text
{
  "name": "pen",
  "tags": [
    "ink",
    "blue"
  ]
}

और इसे वापस लाना:

python
import json

text = '{"name": "pen", "price": 15.0, "stocked": true, "note": null}'
order = json.loads(text)

print(order)
print(type(order["price"]), type(order["stocked"]), order["note"] is None)
text
{'name': 'pen', 'price': 15.0, 'stocked': True, 'note': None}
<class 'float'> <class 'bool'> True

यह CSV से सबसे बड़ा अंतर है। price एक संख्या के रूप में वापस आया और stocked True के रूप में। JSON प्रकारों (types) को साथ रखता है; CSV नहीं रखता।

चार नाम याद रखना आसान है: dumps/loads टेक्स्ट (strings) के साथ काम करते हैं, dump/load फ़ाइलों के साथ काम करते हैं।

JSON क्या वापस नहीं देता

प्रत्येक पायथन ऑब्जेक्ट JSON में नहीं जा सकता:

python
import json

data = {"pair": (1, 2), "numbers": {3, 4}}

print(json.dumps({"pair": data["pair"]}))
print(json.dumps(data))
text
{"pair": [1, 2]}
TypeError: Object of type set is not JSON serializable

एक टपल चुपचाप एक सूची बन जाता है। JSON में कोई टपल नहीं है।

एक सेट बिल्कुल नहीं जा सकता (TypeError)।

JSON कीज़ हमेशा टेक्स्ट होती हैं। संख्यात्मक कीज़ चुपचाप स्ट्रिंग बन जाती हैं: {1: "a"} बन जाता है {"1": "a"}।

सुरक्षित प्रकार: डिक्शनरी, लिस्ट, टेक्स्ट, संख्याएँ, True/False और None।


एक संपूर्ण उदाहरण

items.csv:

text
name,note,price,quantity
pen,blue ink,15.0,3
bag,"large, sturdy",850.0,1
ink,,120.0,2
clip,broken,,4

main.py:

python
"""वस्तुओं की एक CSV पढ़ें, उसका योग करें, और परिणाम को JSON के रूप में लिखें।"""

import csv
import json
from pathlib import Path

TAX_RATE = 0.15


def read_items(path):
    """उपयोग योग्य पंक्तियों और समस्याओं को लौटाता है। csv कोट्स को संभालता है।"""
    items = []
    problems = []

    with open(path, "r", encoding="utf-8", newline="") as fh:
        for number, row in enumerate(csv.DictReader(fh), start=2):
            try:
                items.append({
                    "name": row["name"],
                    "note": row["note"],
                    "amount": round(
                        float(row["price"]) * int(row["quantity"]) * (1 + TAX_RATE), 2),
                })
            except ValueError as err:
                problems.append(f"line {number}: {err}")

    return items, problems


def main():
    items, problems = read_items(Path("items.csv"))

    summary = {
        "items": items,
        "total": round(sum(item["amount"] for item in items), 2),
        "skipped": problems,
    }

    Path("summary.json").write_text(
        json.dumps(summary, indent=2) + "
", encoding="utf-8")

    print(Path("summary.json").read_text(encoding="utf-8"), end="")


if __name__ == "__main__":
    main()
text
{
  "items": [
    {
      "name": "pen",
      "note": "blue ink",
      "amount": 51.75
    },
    {
      "name": "bag",
      "note": "large, sturdy",
      "amount": 977.5
    },
    {
      "name": "ink",
      "note": "",
      "amount": 276.0
    }
  ],
  "total": 1305.25,
  "skipped": [
    "line 5: could not convert string to float: ''"
  ]
}

जब यह टूटता है

मेरी CSV की प्रत्येक पंक्ति के बाद एक खाली पंक्ति आ रही है newline="" पास नहीं किया गया था। लिखते समय इसे पास करें।

TypeError: Object of type set is not JSON serializable एक सेट, डेट या आपका अपना ऑब्जेक्ट पास किया गया था। इसे पहले लिस्ट या टेक्स्ट में बदलें।

मेरे टपल लिस्ट के रूप में वापस आए यह सामान्य है — JSON में टपल नहीं होता। यदि आवश्यक हो तो बाद में tuple(...) कॉल करें।