2016-07-04 62 views
1

我試圖做一些事情,也許是不可能的,也許還是應該以不同的方式來完成...內存錯誤加載1GB .ACCDB使用pypyodbc和熊貓

我要讀1 GB的訪問文件並在熊貓中操作;由於cursor.fetchall()直接與Memory Error失敗,我嘗試了下面的函數以查看內存錯誤何時發生:它在400.000行讀取後出現(總數爲1.12 Mrows)。

這很奇怪,因爲我在我的機器上有8 GB的ram,它似乎是50%的免費。我也將我的虛擬內存設置爲16 GB,但結果沒有改變。

我不需要微積分速度,所以任何骯髒的解決方案是歡迎:)包括使用硬盤作爲ram(我有一個ssd)。

也許有辦法讓所有的內存可用於Python?

  • 單列獲取:cursor.fetchone()
  • 很多行獲取:cursor.fetchmany()
  • 所有行獲取:cursor.fetchall()
  • 大熊貓read_sql傳遞chunksizepandas.read_sql(query, conn, chunksize=chunksize)(感謝那些已經失敗

    方式給用戶MaxU)

功能:

def msaccess_to_df (abs_path, query): 
    conn = pypyodbc.connect(
     r"Driver={Microsoft Access Driver (*.mdb, *.accdb)};" 
     r"Dbq=" + abs_path + ";") 

    cur = conn.cursor() 
    cur.execute(query) 

    fields = zip(*cur.description)[0] 
    df = pandas.DataFrame(columns=fields) 

    fetch_lines_per_block = 5000 
    i = 0 
    while True: 
     rows = cur.fetchmany(fetch_lines_per_block) # <----- 
     if len(rows) == 0: break 
     else: 
      rd = [dict(zip(fields, r)) for r in rows] 
      df = df.append(rd, ignore_index=True) 
      del rows 
      del rd 
     i+=1 
     print 'fetched', i*fetch_lines_per_block, 'lines' 

    cur.close() 
    conn.close() 

    return df 

該錯誤:

df = df.append(rd, ignore_index=True) 
    File "C:\Python27\lib\site-packages\pandas\core\frame.py", line 4338, in append 
    verify_integrity=verify_integrity) 
    File "C:\Python27\lib\site-packages\pandas\tools\merge.py", line 845, in concat 
    copy=copy) 
    File "C:\Python27\lib\site-packages\pandas\tools\merge.py", line 904, in __init__ 
    obj.consolidate(inplace=True) 
    File "C:\Python27\lib\site-packages\pandas\core\generic.py", line 2747, in consolidate 
    self._consolidate_inplace() 
    File "C:\Python27\lib\site-packages\pandas\core\generic.py", line 2729, in _consolidate_inplace 
    self._protect_consolidate(f) 
    File "C:\Python27\lib\site-packages\pandas\core\generic.py", line 2718, in _protect_consolidate 
    result = f() 
    File "C:\Python27\lib\site-packages\pandas\core\generic.py", line 2727, in f 
    self._data = self._data.consolidate() 
    File "C:\Python27\lib\site-packages\pandas\core\internals.py", line 3273, in consolidate 
    bm._consolidate_inplace() 
    File "C:\Python27\lib\site-packages\pandas\core\internals.py", line 3278, in _consolidate_inplace 
    self.blocks = tuple(_consolidate(self.blocks)) 
    File "C:\Python27\lib\site-packages\pandas\core\internals.py", line 4269, in _consolidate 
    _can_consolidate=_can_consolidate) 
    File "C:\Python27\lib\site-packages\pandas\core\internals.py", line 4292, in _merge_blocks 
    new_values = new_values[argsort] 
MemoryError 

####################編輯 - 解決####################

最後我解決了

利用這種方法的任何工作更換訪問驅動程序。

+1

啊!如果您的機器允許,只需推薦Python 64位。請將您的編輯張貼爲未來讀者的答案。 – Parfait

回答

1

我會用本地大熊貓方法 - read_sql(),而不是在循環手動讀取行:

def msaccess_to_df (abs_path, query): 
    conn = pypyodbc.connect(
     r"Driver={Microsoft Access Driver (*.mdb, *.accdb)};" 
     r"Dbq=" + abs_path + ";") 

    df = pd.read_sql(query, conn) 
    conn.close() 
    return df 

如果您仍然收到MemoryError例外,嘗試在塊讀取數據:

def msaccess_to_df (abs_path, query, chunksize=10**5): 
    conn = pypyodbc.connect(
     r"Driver={Microsoft Access Driver (*.mdb, *.accdb)};" 
     r"Dbq=" + abs_path + ";") 

    df = pd.concat([x for x in pd.read_sql(query, conn, chunksize=chunksize)], 
        ignore_index=True) 
    conn.close() 
    return df 

PS這應該給你一個想法,但請注意,我沒有測試這個代碼,所以它可能需要一些調試...

+0

謝謝,但也與'chunksize'我一段時間後仍然有內存錯誤,即使我有3 GB的RAM免費(在Windows資源監視器中查看)。 – DPColombotto