python - पाइथन में लाइन द्वारा लाइन को बड़ी फ़ाइल कैसे पढ़ा जाए




file-read (7)

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

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

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

कोई सुझाव?

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


न्यूलाइन को पट्टी करने के लिए:

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

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

संपादित करें - सार्वभौमिक न्यूलाइन समर्थन निर्दिष्ट करने के लिए:

  • यूनिक्स पर पायथन 2 - open(file_path, mode='rU') - आवश्यक [धन्यवाद @Dave ]
  • विंडोज़ पर पायथन 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 के answer , पायथन के खुले () दस्तावेज़, और iPython प्रयोगों के लिए iPython


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

हालांकि जिस तरह से आपका एल्गोरिदम जाता है, यह फ़ाइल की प्रत्येक पंक्ति के लिए पूरी फ़ाइल को पढ़ता है। इसका मतलब है कि फाइल पढ़ने की कुल मात्रा - और लेवेनशेटिन दूरी की गणना - एन * एन किया जाएगा यदि एन फ़ाइल में लाइनों की मात्रा है। चूंकि आप फ़ाइल आकार के बारे में चिंतित हैं और इसे स्मृति में रखना नहीं चाहते हैं, इसलिए मैं परिणामस्वरूप वर्गबद्ध रनटाइम के बारे में चिंतित हूं। आपका एल्गोरिदम ओ (एन ^ 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)

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


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

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

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

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

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

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

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

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

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

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

[email protected]:/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 एसएसडी है।

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

क्या अच्छा है आप इस शुद्ध मामले में अपने शुद्ध पायथन कार्यक्रम को अनिवार्य रूप से gnu wc संकलित सी प्रोग्राम की गति से मेल खाते हैं। पायथन का अर्थ है लेकिन सी संकलित है, इसलिए यह गति की एक बहुत ही रोचक काम है, मुझे लगता है कि आप सहमत होंगे। बेशक, डब्ल्यूसी को वास्तव में एक समांतर कार्यक्रम में बदलने की जरूरत है, और फिर यह वास्तव में मेरे पायथन कार्यक्रम से मोजे को हरा देगा। लेकिन जैसा कि आज है, gnu 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

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

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

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

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

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 पायथन प्रोग्राम के मुख्य भाग:

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 के लिए def सिर्फ सामान्य अनुक्रमिक कोड है। अगर किसी और ने समानांतर प्रोग्रामिंग की तरह कुछ अभ्यास करना चाहते हैं तो मैंने इसे छोड़ दिया। मैंने आपके सीखने के लाभ के लिए कठिन भागों को मुक्त करने के लिए दिया: परीक्षण और काम करने वाले समानांतर कोड।

धन्यवाद: अरोनो और क्लिफ और एच 2 ओ कर्मचारियों द्वारा उनके महान सॉफ्टवेयर और निर्देशक वीडियो के लिए ओपन-सोर्स एच 2 ओ प्रोजेक्ट, जिसने मुझे ऊपर दिखाए गए इस शुद्ध पायथन उच्च प्रदर्शन समांतर बाइट ऑफ़सेट रीडर के लिए प्रेरणा प्रदान की है। एच 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

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

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

यह एक पूर्ण सूची आवंटित नहीं करता है। यह लाइनों पर फिर से शुरू होता है।


रैंकिंग क्रम में दो मेमोरी कुशल तरीके (पहले सर्वोत्तम है) -

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

1. के with उपयोग करें

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

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

2. yield उपयोग

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

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() फ़ंक्शन के लिए लागू होता है read() पूरी फ़ाइल को स्मृति में लोड करता है, फिर उस पर पुनरावृत्ति करता है। fileinput मॉड्यूल का उपयोग करने के लिए बड़ी फ़ाइलों के लिए थोड़ा बेहतर दृष्टिकोण (पहला उल्लेख किया गया दो तरीकों सबसे अच्छा है) निम्नानुसार है:

import fileinput

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

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

संदर्भ

  1. स्टेटमेंट के साथ पायथन

#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






file-read