एक list
. के रूप में अपनी संपूर्ण इनपुट फ़ाइल को मेमोरी में डालने से बचकर एक महत्वपूर्ण बचत की जा सकती है पंक्तियों का।
विशेष रूप से, ये पंक्तियाँ स्मृति उपयोग पर भयानक हैं, इसमें वे bytes
के चरम स्मृति उपयोग को शामिल करते हैं अपनी पूरी फ़ाइल के आकार पर आपत्ति जताएं, साथ ही एक list
फ़ाइल की संपूर्ण सामग्री के साथ पंक्तियाँ:
file_content = obj['Body'].read().decode('utf-8').splitlines(True)
for line in file_content:
64 बिट पायथन 3.3+ पर 5 मिलियन लाइनों वाली 1 जीबी ASCII टेक्स्ट फ़ाइल के लिए, यह सिर्फ के लिए लगभग 2.3 जीबी की अधिकतम मेमोरी आवश्यकता है। bytes
ऑब्जेक्ट, list
, और व्यक्तिगत str
list
में s . एक प्रोग्राम जिसे 2.3x जितनी अधिक RAM की आवश्यकता होती है, उतनी ही फ़ाइलों का आकार जो इसे संसाधित करता है, बड़ी फ़ाइलों के पैमाने पर नहीं होगा।
ठीक करने के लिए, उस मूल कोड को इसमें बदलें:
file_content = io.TextIOWrapper(obj['Body'], encoding='utf-8')
for line in file_content:
यह देखते हुए कि obj['Body']
आलसी स्ट्रीमिंग के लिए प्रयोग करने योग्य प्रतीत होता है
इसे दोनों को हटा देना चाहिए मेमोरी से संपूर्ण फ़ाइल डेटा की प्रतियां। TextIOWrapper
. का उपयोग करना मतलब obj['Body']
(एक समय में कुछ केबी की) आलस्य से पढ़ा और डिकोड किया जाता है, और लाइनों को आलसी रूप से भी पुनरावृत्त किया जाता है; यह फ़ाइल आकार की परवाह किए बिना स्मृति मांगों को एक छोटी, बड़े पैमाने पर निश्चित मात्रा में कम कर देता है (उच्चतम स्मृति लागत सबसे लंबी लाइन की लंबाई पर निर्भर करेगी)।
अपडेट करें:
ऐसा लगता है StreamingBody
io.BufferedIOBase
. को लागू नहीं करता है एबीसी. इसमें अपने स्वयं के प्रलेखित API
हैं। हालांकि, इसका उपयोग एक समान उद्देश्य के लिए किया जा सकता है। अगर आप TextIOWrapper
नहीं बना सकते हैं अपने लिए काम करें (यदि इसे काम करने के लिए बनाया जा सकता है तो यह बहुत अधिक कुशल और सरल है), एक विकल्प यह होगा:
file_content = (line.decode('utf-8') for line in obj['Body'].iter_lines())
for line in file_content:
TextIOWrapper
का उपयोग करने के विपरीत , यह ब्लॉकों के थोक डिकोडिंग से लाभ नहीं उठाता है (प्रत्येक पंक्ति को अलग-अलग डीकोड किया जाता है), लेकिन अन्यथा इसे कम स्मृति उपयोग के संदर्भ में समान लाभ प्राप्त करना चाहिए।