बड़ी फाइल को कैसे पढ़ें - लाइन बाय लाइन?


536

मैं एक पूरी फ़ाइल की प्रत्येक पंक्ति पर पुनरावृति करना चाहता हूं। ऐसा करने का एक तरीका यह है कि पूरी फ़ाइल को पढ़कर, उसे किसी सूची में सहेजकर, फिर ब्याज की लाइन पर चला जाए। यह विधि बहुत मेमोरी का उपयोग करती है, इसलिए मैं एक विकल्प की तलाश कर रहा हूं।

मेरा कोड अब तक:

for each_line in fileinput.input(input_file):
    do_something(each_line)

    for each_line_again in fileinput.input(input_file):
        do_something(each_line_again)

इस कोड को निष्पादित करना एक त्रुटि संदेश देता है device active:।

कोई सुझाव?

इसका उद्देश्य जोड़ी-वार स्ट्रिंग समानता की गणना करना है, जिसका अर्थ है कि फाइल में प्रत्येक पंक्ति के लिए, मैं हर दूसरी पंक्ति के साथ लेवेंसहाइट दूरी की गणना करना चाहता हूं।


4
आपको प्रत्येक पंक्ति के लिए पूरी फ़ाइल फिर से पढ़ने की आवश्यकता क्यों है? हो सकता है कि अगर आपने बताया कि आप किसी को पूरा करने की कोशिश कर रहे हैं तो बेहतर दृष्टिकोण का सुझाव देने में सक्षम हो सकते हैं।
JJJ

जवाबों:


1269

किसी फ़ाइल को पढ़ने का सही, पूरी तरह से पाइथोनिक तरीका निम्नलिखित है:

with open(...) as f:
    for line in f:
        # Do something with 'line'

withबयान हैंडल खोलने और फ़ाइल को बंद करने, सहित एक अपवाद भीतरी ब्लॉक में उठाया गया है। for line in fव्यवहार करता है फ़ाइल वस्तु fएक iterable, जो स्वत: बफ़र का उपयोग करता है मैं / हे और स्मृति प्रबंधन तो आप बड़ी फ़ाइलों के बारे में चिंता की जरूरत नहीं है के रूप में।

एक होना चाहिए - और अधिमानतः केवल एक - स्पष्ट तरीका यह करने के लिए।


14
हाँ, यह अजगर 2.6 और इसके बाद के संस्करण के साथ सबसे अच्छा संस्करण है
साइमन बर्गोट

3
मैं व्यक्तिगत रूप से डेटा पाइपलाइनों से निपटने के लिए जनरेटर और कोरटाइन पसंद करता हूं।
जुलुपर

4
यदि कोई फ़ाइल एक विशाल पाठ फ़ाइल है, लेकिन एक पंक्ति के साथ और शब्दों को संसाधित करने के लिए विचार के लिए सबसे अच्छी रणनीति क्या होगी?
mfcabrera

4
कोई समझा सकता है कि कैसे for line in f:काम कर रहा है? मेरा मतलब है, फ़ाइल ऑब्जेक्ट पर पुनरावृति कैसे संभव है?
13

11
यदि आप किसी ऑब्जेक्ट पर पुनरावृति करते हैं, तो पायथन ऑब्जेक्ट मेथड्स की सूची में दिखता है जिसे विशेष कहा जाता है __iter__, जो इसे बताता है कि क्या करना है। फ़ाइल ऑब्जेक्ट्स लाइनों पर एक पुनरावृत्ति लौटने के लिए इस विशेष विधि को परिभाषित करते हैं। (मोटे तौर पर।)
कैट्रील

130

क्रमबद्ध क्रम में दो मेमोरी कुशल तरीके (पहला सबसे अच्छा है) -

  1. का उपयोग with- अजगर 2.5 और इसके बाद के संस्करण से समर्थित है
  2. का उपयोग करें yieldयदि आप वास्तव में कितना पढ़ने के लिए पर नियंत्रण करना चाहते हैं

1. का उपयोग with

withबड़ी फ़ाइलों को पढ़ने का अच्छा और कुशल पायथोनिक तरीका है। लाभ - 1) फ़ाइल ऑब्जेक्ट withनिष्पादन ब्लॉक से बाहर निकलने के बाद स्वचालित रूप से बंद हो जाता है । 2) withब्लॉक के अंदर अपवाद हैंडलिंग । 3) मेमोरी forलूप fलाइन द्वारा फाइल ऑब्जेक्ट लाइन के माध्यम से पुनरावृत्त करता है । आंतरिक रूप से यह IO को बफ़र करता है (महंगा IO परिचालनों पर अनुकूलित करने के लिए) और मेमोरी प्रबंधन।

with open("x.txt") as f:
    for line in f:
        do something with data

2. का उपयोग yield

कभी-कभी किसी को प्रत्येक पुनरावृत्ति में पढ़ने के लिए अधिक बारीक नियंत्रण चाहिए। उस मामले में iter और उपज का उपयोग करें । इस पद्धति के साथ ध्यान दें कि एक को अंत में फ़ाइल को बंद करने की आवश्यकता है।

def readInChunks(fileObj, chunkSize=2048):
    """
    Lazy function to read a file piece by piece.
    Default chunk size: 2kB.
    """
    while True:
        data = fileObj.read(chunkSize)
        if not data:
            break
        yield data

f = open('bigFile')
for chuck in readInChunks(f):
    do_something(chunk)
f.close()

नुकसान और पूर्णता के लिए - नीचे दी गई विधियाँ बड़ी फ़ाइलों को पढ़ने के लिए उतनी अच्छी या सुरुचिपूर्ण नहीं हैं, लेकिन कृपया इसे समझने के लिए पढ़ें।

पायथन में, फ़ाइल से लाइनें पढ़ने का सबसे आम तरीका निम्नलिखित है:

for line in open('myfile','r').readlines():
    do_something(line)

जब यह किया जाता है, हालांकि, readlines()फ़ंक्शन ( read()फ़ंक्शन के लिए एक ही लागू होता है) पूरी फ़ाइल को मेमोरी में लोड करता है, फिर उस पर पुनरावृत्ति करता है। बड़ी फ़ाइलों के लिए थोड़ा बेहतर तरीका (पहले उल्लेखित दो तरीके सबसे अच्छे हैं) fileinputमॉड्यूल का उपयोग करना है, इस प्रकार है:

import fileinput

for line in fileinput.input(['myfile']):
    do_something(line)

fileinput.input()कॉल क्रमिक रूप से लाइनों पढ़ता है, लेकिन उन्हें स्मृति में नहीं रखता के बाद वे भी बस तो यह पढ़ने के लिए या कर रहा है, के बाद सेfile में अजगर iterable है।

संदर्भ

  1. बयान के साथ अजगर

9
-1 यह मूल रूप से एक अच्छा विचार नहीं है for line in open(...).readlines(): <do stuff>। आप क्यों?! आपने बिना किसी लाभ के सिर्फ पायथन के चतुर बफ़र वाले IO के सभी लाभ खो दिए हैं।
कैट्रील

5
@ श्रीकर: एक समस्या के सभी संभव समाधान देने के लिए एक समय और एक जगह है; एक शुरुआती शिक्षण कैसे फ़ाइल इनपुट करना है यह नहीं है। गलत उत्तरों से भरी एक लंबी पोस्ट के तल पर सही उत्तर दफन होने से अच्छा शिक्षण नहीं होता है।
कैट्रियल

6
@ श्री: आप शीर्ष पर सही तरीके से लगाकर अपनी पोस्ट को बेहतर बना सकते हैं, फिर उल्लेख करना readlinesऔर यह बताना कि यह करना अच्छी बात क्यों नहीं है (क्योंकि यह फ़ाइल को मेमोरी में पढ़ता है), फिर यह समझाते हुए कि fileinputमॉड्यूल क्या करता है और आप क्यों हो सकता है कि वह अन्य तरीकों का उपयोग करना चाहता हो, फिर यह समझाते हुए कि फ़ाइल को कैसे चून करना IO को बेहतर बनाता है और चैंकिंग फ़ंक्शन का एक उदाहरण देता है (लेकिन यह उल्लेख करते हुए कि पायथन आपके लिए पहले से ही ऐसा करता है, इसलिए आपको इसकी आवश्यकता नहीं है)। लेकिन सिर्फ एक साधारण समस्या को हल करने के लिए पांच तरीके दिए गए हैं, जिनमें से चार इस मामले में गलत हैं, अच्छा नहीं है।
कैट्रील

2
पूर्णता के लिए आप जो भी जोड़ते हैं, उसे अंतिम रूप से जोड़ते हैं, पहले नहीं। पहले उचित रास्ता दिखाओ।
22000 पर m000

6
@katrielalex ने मेरे उत्तर पर दोबारा गौर किया और पाया कि यह पुनर्गठन करता है। मैं देख सकता हूं कि पहले का उत्तर भ्रम पैदा कर सकता था। उम्मीद है कि यह भविष्य के उपयोगकर्ताओं के लिए स्पष्ट कर देगा।
श्रीकर अप्पलाराजु

37

Newlines पट्टी करने के लिए:

with open(file_path, 'rU') as f:
    for line_terminated in f:
        line = line_terminated.rstrip('\n')
        ...

साथ सार्वभौमिक न्यू लाइन समर्थन सभी पाठ फ़ाइल लाइनों के साथ समाप्त किया जा ऐसा लगेगा '\n', जो कुछ भी फाइल में टर्मिनेटर्स, '\r', '\n', या '\r\n'

EDIT - सार्वभौमिक नई लाइन समर्थन निर्दिष्ट करने के लिए:

  • यूनिक्स पर अजगर 2 - open(file_path, mode='rU')- आवश्यक [धन्यवाद @ यादव ]
  • विंडोज पर पायथन 2 open(file_path, mode='rU')- वैकल्पिक
  • पायथन 3 - open(file_path, newline=None)- वैकल्पिक

newlineपैरामीटर केवल अजगर 3 और डिफ़ॉल्ट में समर्थित है Nonemodeकरने के लिए पैरामीटर चूक 'r'सभी मामलों में। Uविंडोज पर पायथन 3. अजगर 2 में पदावनत कुछ अन्य तंत्र अनुवाद करने के लिए प्रकट होता है \r\nकरने के लिए \n

डॉक्स:

देशी लाइन टर्मिनेटर्स को संरक्षित करने के लिए:

with open(file_path, 'rb') as f:
    with line_native_terminated in f:
        ...

बाइनरी मोड अभी भी फ़ाइल को लाइनों में पार्स कर सकता है in। प्रत्येक लाइन में फाइल में जो भी टर्मिनेटर होंगे, वे होंगे।

@Katrielalex के जवाब के लिए धन्यवाद , पायथन का खुला () डॉक्टर, और iPython प्रयोग।


1
पायथन 2.7 पर मुझे open(file_path, 'rU')सार्वभौमिक नई सूचियों को सक्षम करना था ।
डेव

17

यह अजगर में एक फ़ाइल पढ़ने का एक संभावित तरीका है:

f = open(input_file)
for line in f:
    do_stuff(line)
f.close()

यह पूरी सूची आवंटित नहीं करता है। यह तर्ज पर पुनरावृति करता है।


2
हालांकि यह काम करता है, यह निश्चित रूप से विहित तरीका नहीं है। विहित तरीका एक संदर्भ आवरण का उपयोग करना है, जैसे with open(input_file) as f:। यह आपको बचाता है f.close()और सुनिश्चित करता है कि आप गलती से इसे बंद करना न भूलें। मेमोरी को लीक होने से रोकता है और सभी, फाइलों को पढ़ते समय काफी महत्वपूर्ण होता है।
मस्त

1
जैसा @ मस्त ने कहा, वह विहित तरीका नहीं है, इसलिए उसके लिए अपमानजनक है।
अज़ुक्स

12

कुछ संदर्भ सामने हैं कि मैं कहां से आ रहा हूं। कोड स्निपेट अंत में हैं।

जब मैं कर सकता हूं, मैं सुपर उच्च प्रदर्शन समानांतर सीएसवी फ़ाइल रीड्स करने के लिए एच 2 ओ जैसे एक ओपन सोर्स टूल का उपयोग करना पसंद करता हूं, लेकिन यह उपकरण फीचर सेट में सीमित है। मैं अंत में पर्यवेक्षित शिक्षण के लिए H2O क्लस्टर को खिलाने से पहले डेटा साइंस पाइपलाइन बनाने के लिए बहुत सारे कोड लिख रहा हूं।

मैं UCI रेपो से 8GB HIGGS डेटासेट और यहां तक ​​कि डेटा विज्ञान के उद्देश्यों के लिए 40GB CSV फ़ाइलों को मल्टीप्रोसेसिंग लाइब्रेरी के पूल ऑब्जेक्ट और मैप फ़ंक्शन के साथ समानता के बहुत सारे जोड़कर तेजी से पढ़ रहा हूं। उदाहरण के लिए निकटतम पड़ोसी खोजों और डीबीएससीएन और मार्कोव क्लस्टरिंग एल्गोरिदम के साथ क्लस्टरिंग के लिए कुछ समानांतर प्रोग्रामिंग चालाकी की आवश्यकता होती है ताकि कुछ गंभीर रूप से चुनौतीपूर्ण स्मृति और दीवार घड़ी समय की समस्याओं को बायपास किया जा सके।

मैं आमतौर पर पहले ग्नू उपकरण का उपयोग करके भागों में फ़ाइल-वार को तोड़ना पसंद करता हूं और फिर उन सभी को पायथन प्रोग्राम में समानांतर में खोजने और पढ़ने के लिए उन पर ग्लोब-फिल्ममेक करता हूं। मैं आमतौर पर 1000 + आंशिक फ़ाइलों की तरह कुछ का उपयोग करता हूं। इन ट्रिक्स को करने से प्रोसेसिंग स्पीड और मेमोरी लिमिट में काफी मदद मिलती है।

पांडा डेटाफ्रेम .read_csv एकल पिरोया हुआ है ताकि आप समानांतर चालन के लिए नक्शा () चलाकर पांडा को काफी तेज कर सकें। आप यह देखने के लिए htop का उपयोग कर सकते हैं कि सादे पुराने अनुक्रमिक पांडा dataframe.read_csv के साथ, सिर्फ एक कोर पर 100% सीपीयू pd.read_csv में वास्तविक अड़चन है, डिस्क बिल्कुल नहीं।

मुझे जोड़ना चाहिए कि मैं तेज वीडियो कार्ड बस में SSD का उपयोग कर रहा हूं, SATA6 बस में कताई HD नहीं, साथ ही 16 सीपीयू कोर।

इसके अलावा, एक और तकनीक जो मुझे पता चला कि कुछ अनुप्रयोगों में महान काम करता है समानांतर है CSV फ़ाइल एक विशाल फ़ाइल के भीतर सभी को पढ़ती है, प्रत्येक कार्यकर्ता को फ़ाइल में अलग-अलग ऑफसेट करने के बजाय कई बड़ी फ़ाइलों में एक बड़ी फ़ाइल को पूर्व-विभाजित करना शुरू करता है। अजगर की फाइल की तलाश () और प्रत्येक समानांतर कार्यकर्ता में स्ट्रिप्स में बड़ी टेक्स्ट फ़ाइल को पढ़ने के लिए (और) बताएं, अलग-अलग बाइट में स्टार्ट-बाइट और एंड-बाइट के स्थानों पर एक ही समय में सभी समसामयिक ऑफसेट। आप बाइट्स पर एक रेगेक्स फाइंडॉल कर सकते हैं, और लाइनफीड्स की गिनती वापस कर सकते हैं। यह आंशिक राशि है। श्रमिकों के समाप्त होने के बाद जब नक्शा फ़ंक्शन वापस आता है, तो वैश्विक रकम प्राप्त करने के लिए अंत में आंशिक रकम जमा करें।

समानांतर बाइट ऑफसेट चाल का उपयोग करते हुए कुछ उदाहरण बेंचमार्क निम्नलिखित हैं:

मैं 2 फ़ाइलों का उपयोग करता हूं: HIGGS.csv 8 जीबी है। यह UCI मशीन लर्निंग रिपॉजिटरी से है। all_bin .csv 40.4 GB है और मेरे वर्तमान प्रोजेक्ट से है। मैं 2 कार्यक्रमों का उपयोग करता हूं: जीएनयू wc प्रोग्राम जो लिनक्स के साथ आता है, और शुद्ध पायथन फास्ट्रेडरो प्रोग्राम जो मैंने विकसित किया है।

HP-Z820:/mnt/fastssd/fast_file_reader$ ls -l /mnt/fastssd/nzv/HIGGS.csv
-rw-rw-r-- 1 8035497980 Jan 24 16:00 /mnt/fastssd/nzv/HIGGS.csv

HP-Z820:/mnt/fastssd$ ls -l all_bin.csv
-rw-rw-r-- 1 40412077758 Feb  2 09:00 all_bin.csv

ga@ga-HP-Z820:/mnt/fastssd$ time python fastread.py --fileName="all_bin.csv" --numProcesses=32 --balanceFactor=2
2367496

real    0m8.920s
user    1m30.056s
sys 2m38.744s

In [1]: 40412077758. / 8.92
Out[1]: 4530501990.807175

वह कुछ 4.5 जीबी / एस, या 45 जीबी / एस है, फ़ाइल की गति में कमी। यह कोई हार्ड स्पिनिंग नहीं है, मेरे दोस्त। यह वास्तव में एक सैमसंग प्रो 950 एसएसडी है।

नीचे एक ही फ़ाइल के लिए गति बेंचमार्क है जिसे ग्नू wc द्वारा लाइन-काउंट किया गया है, एक शुद्ध सी संकलित कार्यक्रम।

क्या अच्छा है आप देख सकते हैं कि मेरे शुद्ध अजगर कार्यक्रम को अनिवार्य रूप से इस मामले में ग्नू wc संकलित सी कार्यक्रम की गति से मेल खाता है। पायथन की व्याख्या की गई है लेकिन सी संकलित है, इसलिए यह गति का एक बहुत ही दिलचस्प उपलब्धि है, मुझे लगता है कि आप सहमत होंगे। बेशक, डब्ल्यूसी को वास्तव में एक समानांतर कार्यक्रम में बदलने की आवश्यकता है, और फिर यह वास्तव में मेरे अजगर कार्यक्रम से मोजे को हरा देगा। लेकिन जैसा कि यह आज है, ग्नू wc सिर्फ एक अनुक्रमिक कार्यक्रम है। आप वह कर सकते हैं जो आप कर सकते हैं, और अजगर आज समानांतर कर सकते हैं। साइथन संकलन मुझे (कुछ और समय के लिए) मदद कर सकता है। इसके अलावा मेमोरी मैप की गई फ़ाइलों को अभी तक खोजा नहीं गया था।

HP-Z820:/mnt/fastssd$ time wc -l all_bin.csv
2367496 all_bin.csv

real    0m8.807s
user    0m1.168s
sys 0m7.636s


HP-Z820:/mnt/fastssd/fast_file_reader$ time python fastread.py --fileName="HIGGS.csv" --numProcesses=16 --balanceFactor=2
11000000

real    0m2.257s
user    0m12.088s
sys 0m20.512s

HP-Z820:/mnt/fastssd/fast_file_reader$ time wc -l HIGGS.csv
11000000 HIGGS.csv

real    0m1.820s
user    0m0.364s
sys 0m1.456s

निष्कर्ष: C प्रोग्राम की तुलना में शुद्ध पायथन प्रोग्राम के लिए गति अच्छी है। हालांकि, यह सी प्रोग्राम पर शुद्ध पायथन प्रोग्राम का उपयोग करने के लिए पर्याप्त नहीं है, कम से कम linecounting उद्देश्य के लिए। आम तौर पर तकनीक का उपयोग अन्य फ़ाइल प्रसंस्करण के लिए किया जा सकता है, इसलिए यह अजगर कोड अभी भी अच्छा है।

प्रश्न: क्या रेगेक्स को केवल एक बार संकलित करने और इसे सभी श्रमिकों को पास करने से गति में सुधार होगा? उत्तर: रेगेक्स पूर्व-संकलन इस आवेदन में मदद नहीं करता है। मुझे लगता है कि इसका कारण यह है कि सभी श्रमिकों के लिए प्रक्रिया क्रमिकता और सृजन का अधिपत्य हावी हो रहा है।

एक और चीज़। क्या समानांतर CSV फ़ाइल पढ़ने से भी मदद मिलती है? डिस्क अड़चन है, या यह सीपीयू है? स्टैकओवरफ्लो पर कई तथाकथित टॉप रेटेड जवाबों में सामान्य देव ज्ञान होता है जो आपको एक फ़ाइल को पढ़ने के लिए केवल एक थ्रेड की आवश्यकता होती है, सबसे अच्छा आप कर सकते हैं, वे कहते हैं। क्या वे निश्चित हैं, हालांकि?

चलो पता करते हैं:

HP-Z820:/mnt/fastssd/fast_file_reader$ time python fastread.py --fileName="HIGGS.csv" --numProcesses=16 --balanceFactor=2
11000000

real    0m2.256s
user    0m10.696s
sys 0m19.952s

HP-Z820:/mnt/fastssd/fast_file_reader$ time python fastread.py --fileName="HIGGS.csv" --numProcesses=1 --balanceFactor=1
11000000

real    0m17.380s
user    0m11.124s
sys 0m6.272s

अरे हाँ, हाँ यह करता है। समानांतर फाइल रीडिंग काफी अच्छी तरह से काम करती है। अच्छा तो तुम जाओ!

Ps। यदि आप में से कुछ जानना चाहते हैं, तो क्या होगा अगर एक कार्यकर्ता प्रक्रिया का उपयोग करते समय शेष राशि 2 थी? खैर, यह भयानक है:

HP-Z820:/mnt/fastssd/fast_file_reader$ time python fastread.py --fileName="HIGGS.csv" --numProcesses=1 --balanceFactor=2
11000000

real    1m37.077s
user    0m12.432s
sys 1m24.700s

Fastread.py python program के मुख्य भाग:

fileBytes = stat(fileName).st_size  # Read quickly from OS how many bytes are in a text file
startByte, endByte = PartitionDataToWorkers(workers=numProcesses, items=fileBytes, balanceFactor=balanceFactor)
p = Pool(numProcesses)
partialSum = p.starmap(ReadFileSegment, zip(startByte, endByte, repeat(fileName))) # startByte is already a list. fileName is made into a same-length list of duplicates values.
globalSum = sum(partialSum)
print(globalSum)


def ReadFileSegment(startByte, endByte, fileName, searchChar='\n'):  # counts number of searchChar appearing in the byte range
    with open(fileName, 'r') as f:
        f.seek(startByte-1)  # seek is initially at byte 0 and then moves forward the specified amount, so seek(5) points at the 6th byte.
        bytes = f.read(endByte - startByte + 1)
        cnt = len(re.findall(searchChar, bytes)) # findall with implicit compiling runs just as fast here as re.compile once + re.finditer many times.
    return cnt

PartitionDataToWorkers के लिए हार सिर्फ साधारण अनुक्रमिक कोड है। मैंने इसे छोड़ दिया मामले में किसी और को समानांतर प्रोग्रामिंग की तरह कुछ अभ्यास प्राप्त करना चाहता है। मैंने कठिन भागों को मुफ्त में दे दिया: आपके सीखने के लाभ के लिए परीक्षण किया गया और समानांतर कोड काम कर रहा है।

इसके लिए धन्यवाद: Arno और Cliff और उनके महान सॉफ्टवेयर और निर्देशात्मक वीडियो के लिए H2O परियोजना का ओपन-सोर्स H2O प्रोजेक्ट, जिसने मुझे ऊपर दिखाए गए अनुसार इस शुद्ध अजगर उच्च प्रदर्शन समानांतर बाइट ऑफसेट रीडर के लिए प्रेरणा प्रदान की है। H2O समानांतर फाइल रीडिंग करता है जावा का उपयोग करके, अजगर और आर कार्यक्रमों द्वारा कॉल करने योग्य है, और बड़ी सीएसवी फ़ाइलों को पढ़ने पर ग्रह पर कुछ भी तेजी से तेजी से पागल है।


समानांतर विखंडू यह क्या है, मूल रूप से। इसके अलावा, मुझे उम्मीद है कि एसएसडी और फ्लैश इस तकनीक के साथ एकमात्र संगत भंडारण उपकरण हैं। कताई HD संगत होने की संभावना नहीं है।
ज्योफ्री एंडरसन

1
आप ओएस कैशिंग डिस्क फ़ाइलों के लिए कैसे खाते हैं?
जेम्सटॉमसमा 1919

5

Katrielalex ने एक फ़ाइल को खोलने और पढ़ने का तरीका प्रदान किया।

हालाँकि जिस तरह से आपका एल्गोरिथ्म चला जाता है वह फ़ाइल की प्रत्येक पंक्ति के लिए पूरी फ़ाइल को पढ़ता है। इसका मतलब है कि किसी फ़ाइल को पढ़ने की कुल मात्रा - और लेवेंसहाइट दूरी की गणना - एन * एन किया जाएगा यदि एन फ़ाइल में लाइनों की मात्रा है। चूंकि आप फ़ाइल आकार के बारे में चिंतित हैं और इसे स्मृति में नहीं रखना चाहते हैं, इसलिए मैं परिणामी द्विघात रनटाइम के बारे में चिंतित हूं । आपका एल्गोरिथ्म एल्गोरिदम के O (n ^ 2) वर्ग में है जिसे अक्सर विशेषज्ञता के साथ बेहतर बनाया जा सकता है।

मुझे संदेह है कि आप यहां पहले से ही मेमोरी बनाम रनटाइम के ट्रेडऑफ को जानते हैं, लेकिन शायद आप जांच करना चाहेंगे कि समानांतर में कई लेवेंसहाइट दूरी की गणना करने का एक कुशल तरीका है या नहीं। यदि हां, तो यहां आपके समाधान को साझा करना दिलचस्प होगा।

आपकी फ़ाइलों की कितनी पंक्तियाँ हैं, और किस प्रकार की मशीन (मेम एंड सीपीयू पॉवर) पर आपके एल्गोरिदम को चलना है, और सहनशील रनटाइम क्या है?

कोड जैसा दिखेगा:

with f_outer as open(input_file, 'r'):
    for line_outer in f_outer:
        with f_inner as open(input_file, 'r'):
            for line_inner in f_inner:
                compute_distance(line_outer, line_inner)

लेकिन सवाल यह है कि आप दूरी (मैट्रिक्स?) को कैसे संग्रहीत करते हैं और क्या आप प्रसंस्करण के लिए बाहरी_लाइन तैयार करने या पुन: उपयोग के लिए कुछ मध्यवर्ती परिणामों को कैशिंग करने के लिए तैयारी का लाभ प्राप्त कर सकते हैं।


मेरा कहना यह है कि इस पोस्ट में सवाल का जवाब नहीं है, बस कुछ और सवाल हैं! IMO यह एक टिप्पणी के रूप में बेहतर अनुकूल होगा।
कट्रील

1
@ कैटरीलेक्स: एर्र। अजीब। आपने नेस्टेड लूप्स को देखा, वास्तविक प्रश्न को फिट करने के लिए अपने स्वयं के उत्तर का विस्तार किया? मैं अपने प्रश्नों को अपने उत्तर से यहाँ हटा सकता हूँ, और इसमें अभी तक पर्याप्त सामग्री है जो इसे आंशिक - उत्तर के रूप में प्रदान करती है। मैं यह भी स्वीकार कर सकता हूं कि क्या आप नेस्टेड लूप उदाहरण को शामिल करने के लिए अपना स्वयं का उत्तर संपादित करेंगे - जो स्पष्ट रूप से प्रश्न द्वारा पूछा गया था - और फिर मैं अपना जवाब खुशी से निकाल सकता हूं। लेकिन एक गिरावट कुछ है जो मुझे बिल्कुल नहीं मिलती है।
cfi

काफी उचित; मैं वास्तव में सवाल के जवाब के रूप में छोरों के लिए नेस्टेड का प्रदर्शन नहीं देखता हूं, लेकिन मुझे लगता है कि यह शुरुआती लोगों पर बहुत दृढ़ता से लक्षित है। डाउनवोट हटा दिया गया।
कट्रील

3
#Using a text file for the example
with open("yourFile.txt","r") as f:
    text = f.readlines()
for line in text:
    print line
  • पढ़ने के लिए अपनी फ़ाइल खोलें (आर)
  • पूरी फ़ाइल पढ़ें और प्रत्येक पंक्ति को सूची (पाठ) में सहेजें
  • प्रत्येक पंक्ति को मुद्रित करने वाली सूची के माध्यम से लूप करें।

यदि आप चाहते हैं, उदाहरण के लिए, 10 से अधिक की लंबाई के लिए एक विशिष्ट रेखा की जांच करने के लिए, जो आपके पास पहले से उपलब्ध है, उसके साथ काम करें।

for line in text:
    if len(line) > 10:
        print line

1
इस प्रश्न के लिए सबसे अच्छा नहीं है, लेकिन यह कोड मुख्य रूप से उस स्थिति में उपयोगी है, जब आप "slurping" देख रहे हों (एक ही बार में पूरी फ़ाइल को पढ़ना)। यह मेरा मामला था और गूगल मुझे यहां मिल गया। +1। इसके अलावा, परमाणुता के लिए, या यदि आप समय लेते हैं तो लूप में प्रोसेसिंग की प्रक्रिया पूरी फाइल को पढ़ने के लिए तेजी से समाप्त हो सकती है
ntg

1
इसके अलावा, कोड में थोड़ा सुधार किया: 1. के बाद की जरूरत नहीं है: ( docs.python.org/2/tutorial/inputoutput.html के साथ , "यह कीवर्ड के साथ उपयोग करने के लिए अच्छा अभ्यास है ...") 2 । फ़ाइल को पढ़ने के बाद संसाधित किया जा सकता है (लूप के साथ ouside ....)
ntg

2

फाइलिनपुट .input () के लिए अजगर प्रलेखन से :

यदि सूची खाली है sys.argv[1:], तो डिफ़ॉल्ट रूप से सूचीबद्ध सभी फ़ाइलों की तर्ज पर यह पुनरावृत्ति करता sys.stdinहै

इसके अलावा, फ़ंक्शन की परिभाषा है:

fileinput.FileInput([files[, inplace[, backup[, mode[, openhook]]]]])

लाइनों के बीच में पढ़ने, यह मुझे बताता है कि files एक सूची हो सकती है ताकि आप कुछ ऐसा कर सकें:

for each_line in fileinput.input([input_file, input_file]):
  do_something(each_line)

अधिक जानकारी के लिए यहाँ देखें


2

मैं दृढ़ता से डिफ़ॉल्ट फ़ाइल लोडिंग का उपयोग नहीं करने की सलाह दूंगा क्योंकि यह बहुत धीमी गति से है। आपको संख्यात्मक कार्यों और IOpro कार्यों (जैसे numpy.loadtxt ()) में देखना चाहिए।

http://docs.scipy.org/doc/numpy/user/basics.io.genfromtxt.html

https://store.continuum.io/cshop/iopro/

तब आप अपने जोड़ीदार ऑपरेशन को विखंडू में तोड़ सकते हैं:

import numpy as np
import math

lines_total = n    
similarity = np.zeros(n,n)
lines_per_chunk = m
n_chunks = math.ceil(float(n)/m)
for i in xrange(n_chunks):
    for j in xrange(n_chunks):
        chunk_i = (function of your choice to read lines i*lines_per_chunk to (i+1)*lines_per_chunk)
        chunk_j = (function of your choice to read lines j*lines_per_chunk to (j+1)*lines_per_chunk)
        similarity[i*lines_per_chunk:(i+1)*lines_per_chunk,
                   j*lines_per_chunk:(j+1)*lines_per_chunk] = fast_operation(chunk_i, chunk_j) 

यह लगभग हमेशा बहुत तेजी से डेटा को चन्नों में लोड करने के लिए होता है और फिर उस पर मैट्रिक्स ऑपरेशन करते हैं, जैसे कि यह तत्व से तत्व करता है !!


0

अंतिम स्थिति पढ़ने से बड़ी फ़ाइल को अक्सर पढ़ने की आवश्यकता है?

मैंने Apache access.log फ़ाइल को दिन में कई बार काटने के लिए उपयोग की जाने वाली स्क्रिप्ट बनाई है। इसलिए मुझे अंतिम निष्पादन के दौरान अंतिम पंक्ति में स्थिति कर्सर सेट करने की आवश्यकता थी । यह अंत करने के लिए, मैंने उपयोग किया file.seek()और file.seek()तरीके जो फ़ाइल में कर्सर के भंडारण की अनुमति देता है।

मेरा कोड:

ENCODING = "utf8"
CURRENT_FILE_DIR = os.path.dirname(os.path.abspath(__file__))

# This file is used to store the last cursor position
cursor_position = os.path.join(CURRENT_FILE_DIR, "access_cursor_position.log")

# Log file with new lines
log_file_to_cut = os.path.join(CURRENT_FILE_DIR, "access.log")
cut_file = os.path.join(CURRENT_FILE_DIR, "cut_access", "cut.log")

# Set in from_line 
from_position = 0
try:
    with open(cursor_position, "r", encoding=ENCODING) as f:
        from_position = int(f.read())
except Exception as e:
    pass

# We read log_file_to_cut to put new lines in cut_file
with open(log_file_to_cut, "r", encoding=ENCODING) as f:
    with open(cut_file, "w", encoding=ENCODING) as fw:
        # We set cursor to the last position used (during last run of script)
        f.seek(from_position)
        for line in f:
            fw.write("%s" % (line))

    # We save the last position of cursor for next usage
    with open(cursor_position, "w", encoding=ENCODING) as fw:
        fw.write(str(f.tell()))

-2

बड़ी फाइल को पढ़ने का सबसे अच्छा तरीका, लाइन बाय लाइन पायथन एन्युमरेट फ़ंक्शन का उपयोग करना है

with open(file_name, "rU") as read_file:
    for i, row in enumerate(read_file, 1):
        #do something
        #i in line of that line
        #row containts all data of that line

3
क्यों किसी भी बेहतर का उपयोग कर रहा है? स्वीकृत उत्तर पर एकमात्र लाभ यह है कि आपको एक इंडेक्स मिलता है, जिसे ओपी की जरूरत नहीं है और आप कोड को कम पठनीय बना रहे हैं।
फुयस
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.