पायथन में फ़ाइल संचालन

पायथन में फ़ाइल संचालन

यह लेख पायथन में फ़ाइल संचालन की व्याख्या करता है।

सुरक्षा, दक्षता और पठनीयता को ध्यान में रखते हुए, यह मार्गदर्शिका मूलभूत से व्यावहारिक तकनीकों तक, अवधारणाओं को चरण-दर-चरण समझाती है।

YouTube Video

पायथन में फ़ाइल संचालन

फ़ाइल संचालन छोटी स्क्रिप्ट से लेकर बड़े अनुप्रयोगों तक एक आवश्यक मूलभूत कौशल है।

फ़ाइल खोलना और बंद करना

सबसे पहले, आइए टेक्स्ट फ़ाइल पढ़ने और लिखने के उदाहरण देखें। with स्टेटमेंट (संदर्भ प्रबंधक) का उपयोग करने से फ़ाइल सही ढंग से बंद हो जाती है।

निम्नलिखित कोड एक टेक्स्ट फ़ाइल खोलता है, उसकी सामग्री पढ़ता है और उन्हें लाइन दर लाइन प्रोसेस करता है।

1# Open and read a text file safely using a context manager.
2with open("example.txt", "r", encoding="utf-8") as f:
3    # Read all lines lazily (as an iterator) and process each line.
4    for line in f:
5        print(line.rstrip())
  • encoding="utf-8" को स्पष्ट रूप से निर्दिष्ट करना प्लेटफ़ॉर्म-निर्भर समस्याओं को कम करने में मदद करता है।
  • बड़ी फ़ाइलों में भी, for line in f मेमोरी कुशल होता है।

लिखना (ओवरराइट और जोड़ना)

फ़ाइलों में लिखते समय मोड पर ध्यान दें। w ओवरराइट के लिए है, a जोड़ने के लिए है। लिखने समय भी with स्टेटमेंट का उपयोग करें।

निम्न कोड ओवरराइट और जोड़ने के मूल उदाहरण दिखाता है।

1# Write (overwrite) to a file.
2with open("output.txt", "w", encoding="utf-8") as f:
3    f.write("First line\n")
4    f.write("Second line\n")
5
6# Append to the same file.
7with open("output.txt", "a", encoding="utf-8") as f:
8    f.write("Appended line\n")
  • यह कोड output.txt में टेक्स्ट लिखता है और फिर उसी फ़ाइल में और टेक्स्ट जोड़ता है। "w" मोड फ़ाइल को ओवरराइट करता है, जबकि "a" मोड मौजूद सामग्री के अंत में एक नई लाइन जोड़ता है।
  • अगर आपको फ़्लश करने की आवश्यकता है तो flush() को कॉल करें, लेकिन आमतौर पर संदर्भ समाप्त होने पर सामग्री स्वतः फ़्लश हो जाती है।
  • अगर कई प्रोसेस या थ्रेड एक साथ लिख सकते हैं तो आपको एक्सक्लूसिव कंट्रोल (जैसे, फ़ाइल लॉकिंग) के बारे में सोचना चाहिए।

बाइनरी डेटा पढ़ना और लिखना

इमेज और संपीड़ित (कम्प्रेस्ड) फ़ाइलें बाइनरी मोड (rb या wb) में संभाली जाती हैं। टेक्स्ट मोड के विपरीत, encoding की अनदेखी की जाती है।

निम्नलिखित कोड एक बाइनरी फ़ाइल पढ़ता है और उसे बाइनरी मोड में दूसरी फ़ाइल में कॉपी करता है।

1# Read and write binary files.
2with open("image.png", "rb") as src:
3    data = src.read()
4
5with open("copy.png", "wb") as dst:
6    dst.write(data)
  • बड़ी बाइनरी फ़ाइलों को संभालते समय, read() के साथ सब कुछ एक साथ ना पढ़ें; टुकड़ों (chunks) में पढ़ना-लिखना मेमोरी के लिहाज से अधिक कुशल है।

बड़ी फ़ाइलों को टुकड़ों में संभालने का उदाहरण

बहुत बड़ी फ़ाइलें जो मेमोरी में नहीं समातीं, उन्हें निश्चित आकार के टुकड़ों में पढ़ें और लिखें। चूंकि यह इनपुट/आउटपुट (I/O) पर निर्भर है, बफ़र आकार को समायोजित करना उपयोगी है।

निम्नलिखित कोड एक फ़ाइल को 64KB टुकड़ों में कॉपी करता है। इससे तेज़ी से काम होता है और मेमोरी की खपत भी कम रहती है।

1# Copy a large file in chunks to avoid using too much memory.
2CHUNK_SIZE = 64 * 1024  # 64 KB
3
4with open("large_source.bin", "rb") as src,      open("large_dest.bin", "wb") as dst:
5    while True:
6        chunk = src.read(CHUNK_SIZE)
7        if not chunk:
8            break
9        dst.write(chunk)
  • आप अपने नेटवर्क या डिस्क की विशेषताओं के अनुसार टुकड़े का आकार समायोजित कर सकते हैं। SSD पर, थोड़ा बड़ा टुकड़ा आकार अक्सर बेहतर काम करता है।

बफ़रिंग आर्ग्युमेंट का उपयोग करने का उदाहरण

open() फ़ंक्शन में buffering आर्ग्युमेंट को निर्दिष्ट करके, आप पाइथन द्वारा आंतरिक रूप से प्रयुक्त बफ़र आकार को नियंत्रित कर सकते हैं। यह आपको इनपुट/आउटपुट दक्षता को और अनुकूलित करने की अनुमति देता है।

 1# Explicitly set the internal buffer size to 128 KB for faster I/O.
 2CHUNK_SIZE = 64 * 1024
 3BUFFER_SIZE = 128 * 1024  # 128 KB internal buffer
 4
 5with open("large_source.bin", "rb", buffering=BUFFER_SIZE) as src,      open("large_dest.bin", "wb", buffering=BUFFER_SIZE) as dst:
 6    while True:
 7        chunk = src.read(CHUNK_SIZE)
 8        if not chunk:
 9            break
10        dst.write(chunk)
  • यदि आप buffering का मान 0 सेट करते हैं, तो इनपुट/आउटपुट बिना बफ़रिंग के किया जाता है; 1 के लिए लाइन बफ़रिंग सक्षम होती है, जबकि 2 या इससे अधिक के मान निर्दिष्ट बाइट्स आकार के बफ़र का उपयोग करते हैं।
  • आम तौर पर, डिफ़ॉल्ट मान पर्याप्त होता है क्योंकि ऑपरेटिंग सिस्टम कैशिंग को कुशलता से संभालता है, लेकिन बहुत बड़ी फ़ाइलों या विशेष डिवाइसों के लिए इस पैरामीटर को समायोजित करना प्रभावी हो सकता है।

पाथलिब का उपयोग करते हुए आधुनिक फ़ाइल संचालन

मानक pathlib मॉड्यूल पथ (path) को संभालना अधिक सहज बनाता है। यह स्ट्रिंग पथ की तुलना में पठनीयता और सुरक्षा में सुधार करता है।

 1from pathlib import Path
 2
 3path = Path("data") / "notes.txt"
 4
 5# Ensure parent directory exists.
 6path.parent.mkdir(parents=True, exist_ok=True)
 7
 8# Write and read using pathlib.
 9path.write_text("Example content\n", encoding="utf-8")
10content = path.read_text(encoding="utf-8")
11print(content)
  • यह कोड pathlib का उपयोग कर एक निर्देशिका बनाने, एक टेक्स्ट फ़ाइल में लिखने और उसकी सामग्री पढ़ने का प्रदर्शन करता है। Path ऑब्जेक्ट के साथ, आप पथों को सहज और सुरक्षित दोनों तरीकों से संभाल सकते हैं।
  • Path में iterdir() और glob() जैसी सुविधाजनक APIs होती हैं। आप कोड बिना यह सोचे लिख सकते हैं कि अलग-अलग ऑपरेटिंग सिस्टम में पथ विभाजक कैसे हैं।

अस्थायी फ़ाइलें और निर्देशिकाएँ (tempfile)

tempfile का प्रयोग करके अस्थायी फ़ाइलें सुरक्षित रूप से बनाई जा सकती हैं। यह सुरक्षा से जुड़े रेस कंडीशन और नाम टकराव (collisions) से बचाता है।

निम्न कोड अस्थायी फ़ाइल का उपयोग कर अस्थायी डेटा बनाने का उदाहरण दिखाता है।

 1import tempfile
 2
 3# Create a temporary file that is deleted on close.
 4with tempfile.NamedTemporaryFile(
 5    mode="w+",
 6    encoding="utf-8",
 7    delete=True
 8) as tmp:
 9    tmp.write("temporary data\n")
10    tmp.seek(0)
11    print(tmp.read())
12
13# tmp is deleted here
  • यह कोड एक अस्थायी फ़ाइल बनाता है, डेटा लिखता एवं पढ़ता है, और with ब्लॉक समाप्त होने पर इसे स्वतः हटा देता है। tempfile.NamedTemporaryFile का उपयोग कर आप अस्थायी फ़ाइलों को सुरक्षित एवं बिना टकराव के संभाल सकते हैं। delete=True निर्दिष्ट होने के कारण फ़ाइल स्वतः हटा दी जाती है।
  • Windows पर, आप फ़ाइल को दूसरे हैंडल से तुरंत नहीं खोल सकते, इसलिए आप delete=False सेट कर सकते हैं और हटाने का प्रबंधन खुद कर सकते हैं।

shutil: कॉपी, स्थानांतरण और हटाने के उच्च-स्तरीय संचालन

shutil के साथ फाइलों और निर्देशिकाओं की पुनरावर्ती (recursive) कॉपी, स्थानांतरण और हटाना आसान है।

 1import shutil
 2
 3# Copy a file preserving metadata.
 4shutil.copy2("source.txt", "dest.txt")
 5
 6# Move a file or directory.
 7shutil.move("old_location", "new_location")
 8
 9# Remove an entire directory tree (use with caution).
10shutil.rmtree("some_directory")
  • shutil.copy2 मेटाडेटा (जैसे कि संशोधन समय) भी कॉपी करता है। अगर पुनः नामकरण (rename) उपयोग नहीं किया जा सकता, तो move फ़ाइल को स्थानांतरित करने के लिए अन्य विधि आज़माएगा।
  • rmtree एक खतरनाक प्रक्रिया है, इसलिए हटाने से पहले हमेशा पुष्टि करें और बैकअप लें।

फ़ाइल मेटाडेटा (os.stat) और अनुमति प्रबंधन

os और stat के साथ, फ़ाइल का आकार, संशोधन समय और अनुमतियाँ पढ़ी व बदली जा सकती हैं।

निम्न कोड os.stat से बुनियादी फ़ाइल जानकारी प्राप्त करता है और os.chmod से अनुमतियाँ बदलता है।

 1import os
 2import stat
 3from datetime import datetime
 4
 5st = os.stat("example.txt")
 6print("size:", st.st_size)
 7print("modified:", datetime.fromtimestamp(st.st_mtime))
 8
 9# Make file read-only for owner.
10os.chmod("example.txt", stat.S_IREAD)
  • POSIX और Windows प्रणालियों पर अनुमतियाँ अलग-ढंग से काम करती हैं। अगर क्रॉस-प्लेटफार्म संगतता महत्वपूर्ण है, तो उच्च-स्तरीय API का उपयोग करें या शर्तों के अनुसार प्रबंधन जोड़ें।

फ़ाइल लॉकिंग (विशिष्ट नियंत्रण) — Unix और Windows के बीच अंतर

जब कई प्रोसेस एक साथ एक ही फ़ाइल तक पहुँचते हैं, तब विशिष्ट नियंत्रण आवश्यक होता है। UNIX में fcntl और Windows में msvcrt का प्रयोग होता है।

निम्न कोड UNIX प्रणालियों पर लिखते समय एक्सक्लूसिव लॉक प्राप्त करने के लिए fcntl.flock का उपयोग करता है।

 1# Unix-style file locking example
 2import fcntl
 3
 4with open("output.txt", "a+", encoding="utf-8") as f:
 5    fcntl.flock(f, fcntl.LOCK_EX)
 6    try:
 7        f.write("Safe write\n")
 8        f.flush()
 9    finally:
10        fcntl.flock(f, fcntl.LOCK_UN)
  • यह कोड UNIX जैसी प्रणालियों पर सुरक्षित रूप से लिखने और फ़ाइल में एक साथ कई लिखावट रोकने के लिए fcntl.flock से एक्सक्लूसिव लॉक प्राप्त करता है। प्रोसेसिंग के बाद हमेशा लॉक छोड़ें, ताकि अन्य प्रोसेस भी पहुँचा सकें।
  • Windows पर, msvcrt.locking() का उपयोग करें। ऊँचे स्तर के उपयोग के लिए, portalocker या filelock जैसी बाहरी लाइब्रेरियाँ आज़माएँ।

एटॉमिक फ़ाइल लिखने के पैटर्न

अपडेट के दौरान फ़ाइल भ्रष्टाचार से बचने के लिए, अस्थायी फ़ाइल में लिखें और सफल होने पर उसे os.replace से बदलें।

अस्थायी फ़ाइल में लिखना और बाद में बदलना, क्रैश होने की स्थिति में भ्रष्टाचार से बचाता है।

 1import os
 2from pathlib import Path
 3import tempfile
 4
 5def atomic_write(path: Path, data: str, encoding="utf-8"):
 6    # Write to a temp file in the same directory and atomically replace.
 7    dirpath = path.parent
 8    with tempfile.NamedTemporaryFile(
 9        mode="w",
10        encoding=encoding,
11        dir=str(dirpath),
12        delete=False
13    ) as tmp:
14        tmp.write(data)
15        tmp.flush()
16        tempname = tmp.name
17
18    # Atomic replacement (on most OSes)
19    os.replace(tempname, str(path))
20
21# Usage
22atomic_write(Path("config.json"), '{"key":"value"}\n')

os.replace एक ही फाइल सिस्टम में एटॉमिक रूप से प्रतिस्थापन करता है। ध्यान दें कि अलग-अलग माउंट्स के बीच एटॉमिकिटी की गारंटी नहीं है।

mmap का उपयोग कर तेज़ एक्सेस (बड़े डेटा के लिए)

बड़ी फ़ाइलों तक रैंडम एक्सेस के लिए, mmap I/O प्रदर्शन बेहतर करता है। यह मुख्य रूप से बाइनरी संचालन से संबंधित है।

निम्न कोड एक फ़ाइल को मेमोरी-मैप करता है और विशिष्ट बाइट रेंज पढ़ता या लिखता है। फ़ाइल का आकार बदलते समय सावधान रहें।

1import mmap
2
3with open("data.bin", "r+b") as f:
4    mm = mmap.mmap(f.fileno(), 0)  # map entire file
5    try:
6        print(mm[:20])  # first 20 bytes
7        mm[0:4] = b"\x00\x01\x02\x03"  # modify bytes
8    finally:
9        mm.close()
  • यह कोड mmap के साथ बाइनरी फ़ाइल को मेमोरी में मैप करता है और सीधे बाइट-स्तर पर पढ़ने/लिखने का काम करता है। मेमोरी मैपिंग से बड़े डेटा सेट पर तेज़ रैंडम एक्सेस संभव होता है।
  • mmap कुशल है, लेकिन गलत इस्तेमाल डेटा की स्थिरता में समस्याएँ ला सकता है। ज़रूरत के अनुसार सिंक्रोनाइज़ करने के लिए flush() को कॉल करें।

CSV / JSON / Pickle: फ़ॉर्मैट के अनुसार पढ़ना और लिखना

विशिष्ट डेटा फ़ॉर्मैट के लिए समर्पित मॉड्यूल होते हैं। CSV के लिए csv, JSON के लिए json, और Python ऑब्जेक्ट के लिए pickle का उपयोग करें।

निम्न कोड CSV और JSON पढ़ने-लिखने के साथ-साथ Pickle इस्तेमाल करने के मूल उदाहरण देता है। Pickle मनमाना कोड चला सकता है, इसलिए अनविश्वसनीय स्रोतों से डेटा लोड करने से बचें।

 1import csv
 2import json
 3import pickle
 4
 5# CSV write
 6with open("rows.csv", "w", encoding="utf-8", newline="") as f:
 7    writer = csv.writer(f)
 8    writer.writerow(["name", "age"])
 9    writer.writerow(["Alice", 30])
10
11# JSON write
12data = {"items": [1, 2, 3]}
13with open("data.json", "w", encoding="utf-8") as f:
14    json.dump(data, f, ensure_ascii=False, indent=2)
15
16# Pickle write (only for trusted environments)
17obj = {"key": "value"}
18with open("obj.pkl", "wb") as f:
19    pickle.dump(obj, f)
  • Windows में अतिरिक्त खाली पंक्तियों से बचने के लिए CSV के लिए newline="" निर्दिष्ट करना सिफारिश की जाती है। ensure_ascii=False के साथ, JSON में UTF-8 अक्षर पठनीय रहते हैं।

संपीड़ित फ़ाइलों का सीधा पढ़ना-लिखना (gzip / bz2 / zipfile)

gzip और zip को सीधे संभालना डिस्क स्थान बचा सकता है। मानक लाइब्रेरी में उसके अनुरूप मॉड्यूल शामिल रहते हैं।

निम्न कोड gzip फ़ाइलों को टेक्स्ट के रूप में पढ़ने और लिखने का सरल उदाहरण है।

1import gzip
2
3# Write gzipped text.
4with gzip.open("text.gz", "wt", encoding="utf-8") as f:
5    f.write("Compressed content\n")
6
7# Read gzipped text.
8with gzip.open("text.gz", "rt", encoding="utf-8") as f:
9    print(f.read())
  • संपीड़न स्तर और प्रारूप के अनुसार संपीड़न अनुपात और गति के बीच एक समझौता होता है।

सुरक्षा और कमजोरियों के उपाय

सुरक्षा और कमजोरियों के उपायों के लिए निम्नलिखित बिंदुओं पर विचार किया जा सकता है।

  • अविश्वसनीय इनपुट का उपयोग फ़ाइल नाम या पथ में प्रत्यक्ष रूप से ना करें।
  • Pickle का उपयोग केवल विश्वसनीय स्रोतों के साथ करें।
  • निष्पादन अनुमति को न्यूनतम करें, और फ़ाइलों को संभालने वाली प्रक्रियाओं को केवल आवश्यक न्यूनतम अनुमति दें।
  • tempfile के साथ अस्थायी फ़ाइलों का उपयोग करें, और सामान्य फ़ाइलें सार्वजनिक निर्देशिकाओं में संग्रहित न करें।

अगर फ़ाइल पथ में यूज़र इनपुट का उपयोग कर रहे हैं, तो सामान्यीकरण (normalization) और सत्यापन जरूरी है। उदाहरण के लिए, Path.resolve() का उपयोग करें और पैरेंट निर्देशिकाएँ जांचें।

 1from pathlib import Path
 2
 3def safe_path(base_dir: Path, user_path: str) -> Path:
 4    candidate = (base_dir / user_path).resolve()
 5    if base_dir.resolve() not in candidate.parents and base_dir.resolve() != candidate:
 6        raise ValueError("Invalid path")
 7    return candidate
 8
 9# Usage
10base = Path("/srv/app/data")
11
12# Raises an exception: attempted path traversal outside `base`
13safe = safe_path(base, '../etc/passwd')
  • वेब एप या सार्वजनिक API में बाहरी इनपुट को फ़ाइल पथ के रूप में प्रयोग करते समय विशेष ध्यान बरतें।

सामान्य पैटर्न का संक्षिप्त सार

  • हमेशा with स्टेटमेंट का उपयोग करें (स्वतः बंद करने के लिए)।
  • टेक्स्ट डेटा के लिए स्पष्ट रूप से encoding निर्दिष्ट करें।
  • बड़ी फ़ाइलों को टुकड़ों में पढ़ें और लिखें।
  • साझा संसाधनों के लिए फ़ाइल लॉकिंग लागू करें।
  • महत्वपूर्ण अपडेट के लिए 'टेम्पररी फ़ाइल में लिखें → os.replace' की एटोमिक पद्धति का प्रयोग करें।
  • जोखिमपूर्ण कार्य (जैसे डिलीट करना या ओवरराइट करना) से पहले हमेशा पुष्टि करें और बैकअप तैयार करें।
  • फ़ाइल पथ के रूप में बाहरी इनपुट उपयोग करते समय सामान्यीकरण और मान्यता अनिवार्य है।

सारांश

फ़ाइल संचालन में सुरक्षित व विश्वसनीय विधियाँ जैसे with स्टेटमेंट, स्पष्ट एनकोडिंग निर्धारण और एटोमिक लिखाई जरूरी हैं। बड़े पैमाने की प्रोसेसिंग या समांतर एक्सेस के लिए डेटा करप्शन और टकराव से बचाव हेतु लॉकिंग व लॉग मैनेजमेंट सिस्टम आवश्यक है। विश्वसनीय फ़ाइल संचालन के लिए कुशलता और सुरक्षा का संतुलन आवश्यक है।

आप हमारे YouTube चैनल पर Visual Studio Code का उपयोग करके ऊपर दिए गए लेख के साथ आगे बढ़ सकते हैं। कृपया YouTube चैनल को भी देखें।

YouTube Video