2013-11-26 66 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写入目标文件。