2013-11-26 93 views
1

我寫上飛下的數據在CSV:列添加到CSV一邊寫CSV

name first file parsed      
STEP ID ELEMENT_ID Fatigue SW Fatigue F1 Fatigue F3 
Step 10 10000  1.30E-07 1.51E-06 2.15E-06 

當我完成解析的第一個文件,並啓動第二我會要添加更多的列如下:

name first file parsed         name first file parsed 
STEP ID ELEMENT_ID Fatigue SW Fatigue F1 Fatigue F3 Fatigue SW Fatigue F1 Fatigue F3 
Step 10 10000  1.30E-07 1.51E-06 2.15E-06 1.30E-07 1.51E-06 2.15E-06 

我讀的文件是巨大的2GB,所以我不能創建列表,我需要在解析時寫入。

有什麼建議嗎?

+0

你不能添加列到現有的CSV文件;恐怕你必須重寫整個文件。 –

回答

4

您不能將列添加到現有的CSV文件;恐怕你必須重寫整個文件。

您可以使用下面的上下文管理,使替換文件更容易一些:

from contextlib import contextmanager 
import io 
import os 


@contextmanager 
def inplace(filename, mode='r', buffering=-1, encoding=None, errors=None, 
      newline=None, backup_extension=None): 
    """Allow for a file to be replaced with new content. 

    yields a tuple of (readable, writable) file objects, where writable 
    replaces readable. 

    If an exception occurs, the old file is restored, removing the 
    written data. 

    mode should *not* use 'w', 'a' or '+'; only read-only-modes are supported. 

    """ 

    # move existing file to backup, create new file with same permissions 
    # borrowed extensively from the fileinput module 
    if set(mode) & set('wa+'): 
     raise ValueError('Only read-only file modes can be used') 

    backupfilename = filename + (backup_extension or os.extsep + 'bak') 
    try: 
     os.unlink(backupfilename) 
    except os.error: 
     pass 
    os.rename(filename, backupfilename) 
    readable = io.open(backupfilename, mode, buffering=buffering, 
         encoding=encoding, errors=errors, newline=newline) 
    try: 
     perm = os.fstat(readable.fileno()).st_mode 
    except OSError: 
     writable = open(filename, 'w' + mode.replace('r', ''), 
         buffering=buffering, encoding=encoding, errors=errors, 
         newline=newline) 
    else: 
     os_mode = os.O_CREAT | os.O_WRONLY | os.O_TRUNC 
     if hasattr(os, 'O_BINARY'): 
      os_mode |= os.O_BINARY 
     fd = os.open(filename, os_mode, perm) 
     writable = io.open(fd, "w" + mode.replace('r', ''), buffering=buffering, 
          encoding=encoding, errors=errors, newline=newline) 
     try: 
      if hasattr(os, 'chmod'): 
       os.chmod(filename, perm) 
     except OSError: 
      pass 
    try: 
     yield readable, writable 
    except Exception: 
     # move backup back 
     try: 
      os.unlink(filename) 
     except os.error: 
      pass 
     os.rename(backupfilename, filename) 
     raise 
    finally: 
     readable.close() 
     writable.close() 
     try: 
      os.unlink(backupfilename) 
     except os.error: 
      pass 

使用此與csv模塊添加列:

with inplace(csvfilename, 'rb') as (infh, outfh): 
    reader = csv.reader(infh) 
    writer = csv.writer(outfh) 

    for row in reader: 
     row += ['new', 'column'] 
     writer.writerow(row) 
+0

感謝您的意見,您的解決方案非常優雅,但我是一名工程師,所以我會使用可怕的合併。 –

+0

contextmanager發佈爲博客文章,擴展了一點支持:http://www.zopatista.com/python/2013/11/26/inplace-file-rewriting/ –

0
  1. 定義一個表示數據的原始(如OriginalData)的類。
  2. 定義從第一個類派生的第二個類,幷包含每個新列(如NewData)的屬性。
  3. 在NewData上創建一個將OriginalData作爲參數的構造函數。讓它將來自OriginalData的數據複製到它自己。
  4. 在NewData上重載ToString(),以便它以您希望它出現在目標文件中的格式返回一個字符串。
  5. 在遍歷行時,將它們讀入到OriginalData實例中。
  6. 加載originalData實例後,將數據複製到NewData實例中,然後填充新屬性以包含數據。
  7. 通過調用NewData的ToString()方法將數據從NewData寫入目標文件。