【问题标题】:fastest way in python to read csv, process each line, and write a new csvpython中读取csv、处理每一行并编写新csv的最快方法
【发布时间】:2015-06-10 11:13:52
【问题描述】:

处理 csv 的每一行并写入新 csv 的最快方法是什么?有没有办法使用最少的内存并且最快?请看下面的代码。它从 API 请求 csv,但通过我评论的 for 循环需要很长时间。另外我认为它正在使用我服务器上的所有内存。

from pandas import *
import csv
import requests

reportResult = requests.get(api,headers=header)
csvReader = csv.reader(utf_8_encoder(reportResult.text))
reportData = []
#for loop takes a long time
for row in csvReader:
  combinedDict  = dict(zip(fields, row))
  combinedDict = cleanDict(combinedDict)
  reportData.append(combinedDict)
reportDF = DataFrame(reportData, columns = fields)
reportDF.to_csv('report.csv',sep=',',header=False,index=False)



def utf_8_encoder(unicode_csv_data):
  for line in unicode_csv_data:
    yield line.encode('utf-8')



def cleanDict(combinedDict):
  if combinedDict.get('a_id', None) is not None:
    combinedDict['a_id'] = int(
        float(combinedDict['a_id']))
    combinedDict['unique_a_id'] = ('1_a_'+
           str(combinedDict['a_id']))
  if combinedDict.get('i_id', None) is not None:
    combinedDict['i_id'] =int(
        float(combinedDict['i_id']))
    combinedDict['unique_i_id'] = ('1_i_'+
         str(combinedDict['i_id']))
 if combinedDict.get('pm', None) is not None:
    combinedDict['pm'] = "{0:.10f}".format(float(combinedDict['pm']))
  if combinedDict.get('s', None) is not None:
    combinedDict['s'] = "{0:.10f}".format(float(combinedDict['s']))
  return combinedDict 

当我运行 python 内存分析器时,为什么 for 循环上的行有内存增量?实际的 for 循环是在内存中保存了一些东西,还是我的 utf-8 转换器搞砸了?

Line #    Mem usage    Increment   Line Contents
================================================
   162 1869.254 MiB 1205.824 MiB     for row in csvReader:
   163                                 #print row
   164 1869.254 MiB    0.000 MiB       combinedDict  = dict(zip(fields, row))

当我也将“@profile”符号放在 utf_8-encoder 函数上时,我看到上面 for 循环上的内存消失了:

   163                               for row in csvReader:

但是现在转换器的 for 循环上有内存(我没有让它像上次那样运行,所以在我执行 ctrl+C 之前它只有 56MB):

Line #    Mem usage    Increment   Line Contents
================================================
   154  663.430 MiB    0.000 MiB   @profile
   155                             def utf_8_encoder(unicode_csv_data):
   156  722.496 MiB   59.066 MiB     for line in unicode_csv_data:
   157  722.496 MiB    0.000 MiB       yield line.encode('utf-8')

【问题讨论】:

    标签: python performance csv memory pandas


    【解决方案1】:

    对于初学者,应该使用来自 itertools 的 izip。见下文。

    from itertools import izip
    
    reportData = []
    for row in csvReader:
        combinedDict  = dict(izip(fields, row))
        combinedDict = cleanDict(combinedDict) #cleaned dict method is probably where the bottle neck is
        reportData.append(combinedDict)
    

    izip 是 zip 的生成器版本,它对内存的影响较小。尽管您可能不会有太大的收获,因为看起来您一次只压缩一件物品。我会看看你的 cleanDict() 函数。它有大量的 if 语句需要评估,因此需要时间。最后,如果您真的迫切需要更快的速度并且无法弄清楚从哪里获得它,请使用

    from concurrent.futures import ProcessPoolExecutor
    

    或者换句话说,看看并行处理。 https://docs.python.org/3/library/concurrent.futures.html

    另外请查看 Python 的 PEP 8 指南。 https://www.python.org/dev/peps/pep-0008/ 你的缩进是错误的。所有缩进应为 4 个空格。如果没有别的,它有助于提高可读性。

    【讨论】:

      【解决方案2】:

      我发现它速度更快,并且没有使用太多内存,我的服务器崩溃以使用数据帧读取 csv:

      from cStringIO import StringIO
      from pandas import *
      
      reportText = StringIO(reportResult.text)
      reportDF = read_csv(reportText, sep=',',parse_dates=False)
      

      然后我可以使用 apply 来处理它,例如:

      def trimFloat(fl):
          if fl is not None:
            res = "{0:.10f}".format(float(fl))
            return res
          else:
            return None
      
      floatCols  = ['a', 'b ']
      for col in floatCols:
          reportDF[col] = reportDF[col].apply(trimFloat)
      
      
      def removePct(reportDF):
        reportDF['c'] = reportDF['c'].apply(lambda x: x.translate(None, '%'))
        return reportDF
      

      我怀疑之前尝试的主要问题与 UTF8 编码器有关

      【讨论】:

        猜你喜欢
        • 2014-09-26
        • 1970-01-01
        • 2014-10-04
        • 2015-02-28
        • 2011-09-27
        • 2019-07-31
        • 2020-06-22
        • 2015-09-13
        相关资源
        最近更新 更多