फ़ाइल क्यों? टेक्स्ट, बाइनरी और CSV फ़ाइलें
वेरिएबल का डेटा RAM में रहता है और प्रोग्राम ख़त्म होते ही मिट जाता है। फ़ाइल डेटा को डिस्क पर स्थायी रूप से रखती है।
- टेक्स्ट फ़ाइल (.txt): पढ़ने योग्य अक्षर। हर पंक्ति EOL (end of line) अक्षर
\nपर ख़त्म होती है। नोटपैड में खुलती है। - बाइनरी फ़ाइल (.dat, .bin): मेमोरी जैसे कच्चे बाइट। नोटपैड में पढ़ी नहीं जाती। तेज़, और pickle से पायथन ऑब्जेक्ट रख सकती है। EOL का कोई बदलाव नहीं।
- CSV फ़ाइल (.csv, comma-separated values): टेक्स्ट फ़ाइल जिसमें हर पंक्ति तालिका की एक पंक्ति है और मान अल्पविराम से अलग हैं, जैसे
1,Asha,92। स्प्रेडशीट में खुलती है।
Absolute और relative पाथ
पाथ पायथन को बताता है कि फ़ाइल कहाँ है।
- Absolute पाथ: ड्राइव की जड़ (root) से पूरा पता, जैसे
C:\\School\\CS\\marks.txtया/home/asha/cs/marks.txt। - Relative पाथ: वर्तमान कार्य फ़ोल्डर (जहाँ प्रोग्राम चल रहा है) से पता।
marks.txt= "इसी फ़ोल्डर में";data/marks.txt= "data उप-फ़ोल्डर में";../marks.txt= "एक फ़ोल्डर ऊपर"।
Windows पाथ में r'C:\School\marks.txt' (raw string) लिखें या दोहरे बैकस्लैश, क्योंकि पाथ के अंदर \n या \t विशेष अक्षर बन जाते हैं।
फ़ाइल खोलना-बंद करना: ओपन मोड और with
f = open('marks.txt', 'r') एक फ़ाइल ऑब्जेक्ट (फ़ाइल हैंडल) देता है। काम के बाद f.close() ज़रूर करें; बंद करने से बफ़र में रुका डेटा भी सहेजा जाता है।
| मोड | अर्थ | फ़ाइल न हो तो | कर्सर |
|---|---|---|---|
| r | केवल पढ़ना (डिफ़ॉल्ट) | FileNotFoundError | शुरू |
| w | केवल लिखना, पुराना डेटा मिटता है | बना देता है | शुरू |
| a | जोड़ना (अंत में) | बना देता है | अंत |
| r+ | पढ़ना और लिखना | एरर | शुरू |
| w+ | लिखना और पढ़ना, मिटाकर | बना देता है | शुरू |
| a+ | जोड़ना और पढ़ना | बना देता है | अंत |
बाइनरी के लिए b जोड़ें: rb, wb, ab, rb+, wb+, ab+।
with स्टेटमेंट
with open('marks.txt', 'r') as f:
data = f.read()
# यहाँ फ़ाइल अपने-आप बंदwith खंड ख़त्म होते ही फ़ाइल बंद कर देता है, अपवाद आने पर भी।
टेक्स्ट फ़ाइल में लिखना: write और writelines
f.write(s)एक स्ट्रिंग लिखता है और लिखे अक्षरों की संख्या लौटाता है। यह newline नहीं जोड़ता;'\n'ख़ुद लिखें।f.writelines(L)लिस्ट की हर स्ट्रिंग एक के बाद एक लिखता है, यह भी newline नहीं जोड़ता।
with open('poem.txt', 'w') as f:
f.write('Roses are red\n')
f.writelines(['Sky is blue\n', 'Python is fun\n'])बिना मिटाए जोड़ना हो तो 'a' मोड लें।
टेक्स्ट फ़ाइल पढ़ना: read, readline, readlines
f.read()बची पूरी फ़ाइल एक स्ट्रिंग में।f.read(n)अधिकतम n अक्षर।f.readline()एक पंक्ति, उसके\nसहित। फ़ाइल के अंत पर''देता है।f.readlines()सारी पंक्तियाँ स्ट्रिंग की लिस्ट में।- पंक्ति-दर-पंक्ति लूप:
for line in f:
# 'T' से शुरू होने वाली पंक्तियाँ गिनो
c = 0
with open('poem.txt') as f:
for line in f:
if line.startswith('T'):
c += 1
print(c)अंत का newline हटाने को line.strip(), शब्दों में तोड़ने को line.split()।
seek() और tell(): फ़ाइल पॉइंटर खिसकाना
फ़ाइल पॉइंटर वह जगह (शुरू से बाइटों में) है जहाँ अगला पढ़ना या लिखना होगा।
f.tell()अभी की जगह बताता है।f.seek(offset, whence)उसे खिसकाता है।whence0 = शुरू से (डिफ़ॉल्ट), 1 = अभी की जगह से, 2 = अंत से। टेक्स्ट मोड में शून्य से अलग offset के साथ केवलwhence = 0सुरक्षित है; बाइनरी में तीनों चलते हैं।
with open('poem.txt') as f:
print(f.read(5)) # 'Roses'
print(f.tell()) # 5
f.seek(0)
print(f.read(3)) # 'Ros'
pickle से बाइनरी फ़ाइल: dump और load
Pickling (सीरियलाइज़ेशन) पायथन ऑब्जेक्ट को बाइटों की धारा में बदलना है। Unpickling बाइटों को वापस ऑब्जेक्ट बनाना।
import pickle
rec = {'roll': 1, 'name': 'Asha', 'marks': 92}
with open('stu.dat', 'wb') as f:
pickle.dump(rec, f)
with open('stu.dat', 'rb') as f:
r = pickle.load(f)
print(r['name']) # Ashaहर dump एक ऑब्जेक्ट लिखता है। सब पढ़ने के लिए EOFError आने तक लूप में load:
with open('stu.dat', 'rb') as f:
try:
while True:
print(pickle.load(f))
except EOFError:
pass
बाइनरी फ़ाइल में खोज, जोड़ना और बदलना
जोड़ना (append)
'ab' में खोलें और नया रिकॉर्ड pickle.dump करें। पुराने रिकॉर्ड बने रहते हैं।
खोज (search)
'rb' में खोलें, एक-एक रिकॉर्ड load करें और फ़ील्ड जाँचें: if r['roll'] == 5: print(r); found = True। लूप के बाद found अब भी False हो तो 'नहीं मिला' छापें।
बदलना (update)
तरीका 1 (आसान): सारे रिकॉर्ड लिस्ट में लोड करें, मेल खाता बदलें, फिर फ़ाइल 'wb' में खोलकर सब दोबारा dump करें।
recs = []
with open('stu.dat', 'rb') as f:
try:
while True:
recs.append(pickle.load(f))
except EOFError:
pass
for r in recs:
if r['roll'] == 2:
r['marks'] = 80
with open('stu.dat', 'wb') as f:
for r in recs:
pickle.dump(r, f)तरीका 2 (उसी जगह): 'rb+' में खोलें, हर load से पहले pos = f.tell() नोट करें, और मेल मिलने पर f.seek(pos) करके बदला रिकॉर्ड dump करें (जब नए रिकॉर्ड का बाइट आकार वही हो)।
CSV फ़ाइलें: csv.writer और csv.reader
import csv
with open('class.csv', 'w', newline='') as f:
w = csv.writer(f)
w.writerow(['Roll', 'Name', 'Marks'])
w.writerows([[1, 'Asha', 92], [2, 'Ravi', 75]])
with open('class.csv', 'r') as f:
for row in csv.reader(f):
print(row) # ['1', 'Asha', '92'] …csv.writer(f)writer ऑब्जेक्ट बनाता है।writerow(list)एक पंक्ति;writerows(list_of_lists)कई पंक्तियाँ।newline=''से Windows पर पंक्तियों के बीच ख़ाली लाइन नहीं आती।csv.reader(f)हर पंक्ति स्ट्रिंग की लिस्ट बनाकर देता है; संख्या के लिएint()करें।delimiter=';'से विभाजक बदल सकते हैं।
करके देखें: छोटी डायरी
ऐसा प्रोग्राम लिखिए जो एक पंक्ति पूछे और उसे 'a' मोड से diary.txt में जोड़े। तीन बार चलाइए। अब एक बार 'w' मोड में खोलकर एक पंक्ति लिखिए। हर बार के बाद diary.txt नोटपैड में खोलिए। आप ख़ुद देखेंगे कि 'w' ने सब मिटा दिया। फिर 3D के आख़िरी कदम में अनुमान लगाइए कि seek और read(n) क्या देंगे।
मुख्य सूत्र और परिभाषाएँ
- open(path, mode) · मोड: r, w, a, r+, w+, a+ (बाइनरी के लिए + b)
- with open(...) as f: → फ़ाइल अपने-आप बंद
- read(n), readline(), readlines() · write(s), writelines(list)
- tell() → जगह · seek(offset, whence) whence 0 शुरू, 1 अभी, 2 अंत
- pickle.dump(obj, f) / obj = pickle.load(f) · EOFError तक लूप
- csv.writer(f).writerow(row) / writerows(rows) · csv.reader(f) → स्ट्रिंग की लिस्टें
हल किए गए उदाहरण
1. कौन-सा मोड लेंगे: (a) पुरानी पंक्तियाँ खोए बिना लॉग में नई जोड़ना (b) हर बार नई रिपोर्ट फ़ाइल बनाना (c) सहेजा बाइनरी रिकॉर्ड पढ़ना?
(a) 'a' (कर्सर अंत पर)। (b) 'w' (बनाता या मिटाता है)। (c) 'rb' (बाइनरी पढ़ना)।
2. poem.txt में है 'Roses are red\nSky is blue\n'। f.readline(), फिर f.read(3), फिर f.tell() क्या देंगे?
readline() → 'Roses are red\n' (14 अक्षर: 13 + newline)। read(3) → 'Sky'। tell() → 14 + 3 = 17 (जहाँ newline 1 बाइट है)।
3. story.txt के शब्द गिनने वाला फ़ंक्शन लिखिए।
def count_words(): with open('story.txt') as f: return len(f.read().split()) print(count_words())
4. notes.txt की 20 अक्षरों से छोटी पंक्तियाँ दिखाने वाला फ़ंक्शन लिखिए।
def short_lines(): with open('notes.txt') as f: for line in f: if len(line.rstrip('\n')) < 20: print(line, end='')
5. बाइनरी फ़ाइल book.dat में रिकॉर्ड [book_no, title, price] हैं। एक रिकॉर्ड जोड़ने का फ़ंक्शन लिखिए।
import pickle def add_book(): rec = [int(input('No: ')), input('Title: '), float(input('Price: '))] with open('book.dat', 'ab') as f: pickle.dump(rec, f)
6. book.dat से 300 से महँगी सारी किताबें दिखाइए; एक भी न मिले तो बताइए।
def costly(): found = False with open('book.dat', 'rb') as f: try: while True: r = pickle.load(f) if r[2] > 300: print(r); found = True except EOFError: pass if not found: print('No such book')
7. book.dat में किताब नंबर 3 की कीमत 450 कीजिए।
सारे रिकॉर्ड EOFError तक लिस्ट में लोड करें, जहाँ r[0] == 3 वहाँ r[2] = 450 करें, फिर 'wb' में खोलकर हर रिकॉर्ड दोबारा dump करें। पूरी फ़ाइल फिर से लिखनी है, इसलिए 'wb'।
8. दो फ़ंक्शन लिखिए: contacts.csv में [id, name, phone] पंक्तियाँ जोड़ना, और सब संपर्कों के नाम छापना।
import csv def add(rows): with open('contacts.csv', 'a', newline='') as f: csv.writer(f).writerows(rows) def names(): with open('contacts.csv') as f: for row in csv.reader(f): print(row[1])
आम गलतियाँ
- डेटा जोड़ने के लिए पुरानी फ़ाइल 'w' में खोलना; सब मिट जाता है। 'a' लें।
- भूल जाना कि write() और writelines() अपने-आप '\n' नहीं जोड़ते।
- pickle को टेक्स्ट मोड फ़ाइल के साथ चलाना; pickle को 'wb', 'rb' या 'ab' चाहिए।
- csv.reader से संख्याएँ मिलने की उम्मीद; वह स्ट्रिंग देता है, int() या float() से बदलें।