python-3.x - 在写入百万行 csv 文件时计算 md5 - 无需将其读入内存
问题描述
计算 md5 需要一个字节流才能通过。我假设在写入一百万行时可以将 csv.writer 作为字节流拦截。在下面的 py 代码中,写入了一百万行,我如何计算 md5 而无需仅为 md5 将文件读入内存?
def query2csv(connection, fileUri, sqlQuery, args):
import csv
tocsvfile = open(fileUri, 'w+')
writer = csv.writer(tocsvfile, delimiter=',', quotechar='"') # , quoting=csv.QUOTE_MINIMAL
#As a huge blob goes into writer, pass through, md5 how?
# I do not want to read the huge file through memory just to compute md5
with connection.cursor() as cur:
cur.execute(sqlQuery, args)
column_names = list(map(lambda x: x[0], cur.description))
writer.writerow(column_names)
writer.writerows(__batch_rows(cur))
解决方案
来自csv.writer的文档(强调我的):
csv.writer(csvfile, dialect='excel', **fmtparams)
返回一个编写器对象,该对象负责将用户的数据转换为给定类文件对象上的分隔字符串。
csvfile
可以是任何带有write()
方法的对象。如果 csvfile 是一个文件对象,它应该用newline=''
.
因此,我们可以拦截对 的调用.write()
,并将数据输入 MD5 流,同时将其传递给真实文件。最简洁的方法是定义一个类,其write
方法只调用一些函数(即一个用于 MD5 流,一个用于文件对象):
import csv
import hashlib
class WriterTee:
def __init__(self, *outs):
self.outs = outs
def write(self, s):
for f in self.outs:
f(s)
def query2csv(connection, fileUri, sqlQuery, args):
md5 = hashlib.md5()
with open(fileUri, 'w+', newline='') as tocsvfile, connection.cursor() as cur:
tee = WriterTee(
tocsvfile.write,
lambda s: md5.update(s.encode())
)
writer = csv.writer(tee, delimiter=',', quotechar='"')
cur.execute(sqlQuery, args)
column_names = list(map(lambda x: x[0], cur.description))
writer.writerow(column_names)
writer.writerows(__batch_rows(cur))
return md5.hexdigest()
我进行了其他一些更改,以管理with
块中的两种资源,并newline=''
按照文档所说的那样使用。
顺便说一句,如果您可以选择,我建议您不要出于任何目的使用 MD5。MD5 并不安全,密码学家从 1996 年就开始反对它。即使您不认为安全属性与您的应用程序相关,使用安全散列算法也没有缺点,而且hashlib
无论您选择哪种算法,API 都是相同的。
推荐阅读
- android - 我收到“未附加到活动”错误
- javascript - 我想知道 Google 搜索自动完成功能的工作原理
- python - 使大型数据集的散点图成为可能 - Python
- c++ - 一行的输入搞砸了,代码都是相似的
- xml - 没有在管理服务器上显示 OSSEC 代理的实际 IP 地址
- r - ggplots2 geom_line 和 geom_point 的组合沿线创建了太多形状
- ruby-on-rails - Rails 新的初始化对象创建一个空记录
- asp.net-core - ASP.NET Core 3.1 如何重定向到 MicrosoftIdentity 提供的 AccountController 中包含的登录操作
- android - Google Play 问题:违反权限政策
- javascript - Pipedrive 网络表单未在反应引导模式中加载