python 中读取 csv、处理每一行并写入新 csv 的最快方法
fastest way in python to read csv, process each line, and write a new csv
处理 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')
对于初学者来说,应该使用 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)
in 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 个空格。如果不出意外,它有助于提高可读性。
我发现它要快得多而且没有使用太多内存我的服务器崩溃使用数据帧来读取 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 编码器有关
处理 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')
对于初学者来说,应该使用 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)
in 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 个空格。如果不出意外,它有助于提高可读性。
我发现它要快得多而且没有使用太多内存我的服务器崩溃使用数据帧来读取 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 编码器有关