2012-11-21 50 views
0

在Python中有關於內存錯誤的問題,但我想問一個更具體的我的情況。我對編程和Python很陌生。解析大文件時出現內存錯誤 - Python

當解析大文本文件(〜8GB),行

mylist = [line.strip('\n').split('|') for line in f] 

導致 「的MemoryError」。

我在Windows XP 64位和12GB內存上運行64位Python [MSC v.1500 64位(AMD64)]。除了安裝更多的RAM之外,我該如何處理這種內存錯誤?

回答

5

由於您嘗試將整個文件存儲在列表中(內存中),內存錯誤即將到來。因此,請嘗試在每行上處理而不是存儲它:

for line in f: 
    data = line.strip('\n').split('|') 
    #do something here with data 
+0

解決了我的問題。謝謝。 – user1839897

3

這取決於您想要對列表執行什麼操作。

myiterator = (line.strip('\n').split('|') for line in f) 

(不:

如果你想在一行接一行的基礎工作,你或許可以把工作使用列表生成的,而不是一個列表理解,這將是這樣做我改變了[...](...))。這將返回一個迭代器而不是一個列表,並且由於for line in f也不會創建列表,所以您將一次加載一行。

如果您想一次處理所有行,您可能必須將其與另一種技術結合使用,以便不使用所有內存。

+0

@ user1839897請注意,創建列表生成器實際上並不執行括號內的代碼。直到你循環生成器爲止,例如使用'for'循環:'對於myiterator:'中的line_parts',這不會發生。 –

+0

確切地說,這也是爲什麼創建這樣的生成器相當便宜,因爲計算只在實際需要時纔會發生。此外,它允許您將計算作爲發生器值的一部分進行處理,因此將其他計算結合在一起很容易,作爲單個值(發生器)的一部分。它仍然可以看作是一個列表,雖然有一些區別(沒有len(),沒有切片,沒有索引等)。 –

1

您應該一定使用懶惰的生成器來一次解析這樣一個巨大的文件,或將文件分成較小的塊。

一種可能性:

def lazy_reader(path): 
    """reads a file one line at a time.""" 
    try: 
     file = open(path, 'r') 
     while True: 
      line = file.readline() 
      if not line: break 
      yield line    # "outputs" the line from the generator 
    except IOError: 
     sys.stderr.write("error while opening file at %s\n" % path) 
     sys.exit(2) 
    finally: 
     file.close() 

,然後你可以消耗你產生這樣的

for line in lazy_reader("path/to/your/file"): 
    do_something_with(line) 

編輯:你也可以在簡潔的結合發電機 「流水線」 的方法:

def parse(generator): 
    for line in generator: yield line.strip('\n').split('|') 

for data in parse(lazy_reader("path/to/your/file")): 
    do_something_with_splitted_array(data) 
+0

好的pythonic答案! – theAlse

+1

不是文件對象的迭代器是否已經懶惰? – l4mpi

+0

@ l4mpi是的,但是將它全部讀入一個列表中,並且['for line in f]'不是 – katrielalex

1

我對它的使用with使錯誤更容易,發電機來定義什麼lines應該看起來像,然後迭代:

with open('somefile') as fin: 
    lines = (line.strip('\n').split('|') for line in fin) 
    for line in lines: 
     pass # do something with line 
相關問題