【问题标题】:how to open a csv in universal new line mode through django upload?如何通过django上传以通用换行模式打开csv?
【发布时间】:2013-12-01 23:08:28
【问题描述】:

我正在尝试以 django 形式上传 csv 文件:

class CSVUploadForm(forms.Form):
    csv_file = forms.FileField(label='Select a CSV file to import:',)

    def clean(self):
        file_csv = self.cleaned_data['csv_file']
        records = csv.reader(open('/mypath/'+file_csv.name, 'rU'), dialect=csv.excel_tab)

我需要以通用换行模式打开文件。我可以使用上面的“打开”方法来做到这一点,但这不适用于这种形式,因为我正在处理的文件是 csv 的内存上传版本。

如何将通用新行模式标志 rU 传递给类似的东西

records = csv.reader(file_csv, dialect=csv.excel_tab)

?

【问题讨论】:

    标签: python django csv django-forms


    【解决方案1】:

    您可以通过以下方式使用str.splitlines()——它会在通用换行符上自动拆分:

    def clean(self):
        file_csv = self.cleaned_data['csv_file']
        lines = file_csv.read().splitlines()
        records = csv.reader(lines, dialect=csv.excel_tab)
    

    如果您担心创建lines 变量的内存成本,您可以强制Django 将文件保存到磁盘上的本地文件中,更改settings.py 中的FILE_UPLOAD_MAX_MEMORY_SIZE 变量(more on this variable here):

    # add to your settings.py
    FILE_UPLOAD_MAX_MEMORY_SIZE = 0
    FILE_UPLOAD_TEMP_DIR = '/tmp'
    

    然后使用通用模式处理 tmp 文件夹中的文件:

    def clean(self):
        file_csv = open(self.cleaned_data['csv_file'].temporary_file_path, 'rU')
        records = csv.reader(file_csv, dialect=csv.excel_tab)
    

    【讨论】:

      【解决方案2】:

      上述解决方案的问题是它一次读取整个文件,在处理大型 csv 文件时无法接受。对于小的 CSV 文件,文件将被保存到磁盘而不是保存在内存中,这也不太好。

      我创建了一个类来处理新行

      class FileWithUniversalNewLine(object):
      
          def __init__(self, file_obj):
              self.file = file_obj
      
          def lines(self):
              buff = ""  # In case of reading incomplete line, buff will temporarly keep the incomplete line
              while True:
                  line = self.file.read(2048)
                  if not line:
                      if buff:
                          yield buff
                      raise StopIteration
      
                  # Convert all new lines into linux new line
                  line = buff + line.replace("\r\n", "\n").replace("\r", "\n")
                  lines = line.split("\n")
                  buff = lines.pop()
                  for sline in lines:
                      yield sline
      
          def close(self):
              self.file.close()
      
          def __exit__(self, *args, **kwargs):
              return self.file.__exit__(*args, **kwargs)
      
          def __enter__(self, *args, **kwargs):
              return self
      
          def __iter__(self):
              return self.lines()
      

      用法:

      csvfile = FileWithUniversalNewLine(file_csv)
      records = csv.reader(csvfile, dialect=csv.excel_tab)
      

      【讨论】:

        猜你喜欢
        • 2011-10-07
        • 2010-12-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-01-26
        • 2016-03-22
        • 2015-04-18
        相关资源
        最近更新 更多