ral*_*len 6 python optimization replace
我是Python 的完全初学者或任何严肃的编程语言.我终于得到了一个原型代码,但我觉得它太慢了.
我的目标是根据我拥有的csv文件在一个目录中找到并替换所有文件(它们是csv)中的一些中文字符.这些文件按年份编号很好,例如2000-01.csv,并且是该目录中的唯一文件.
我将循环遍历大约25个文件,每个文件在500mb附近(大约一百万行).我将使用的字典将有大约300个元素,我将unicode(中文字符)更改为整数.我尝试了一个测试运行,假设一切都线性增长(?),看起来它需要大约一个星期才能运行.
提前致谢.这是我的代码(不要笑!):
# -*- coding: utf-8 -*-
import os, codecs
dir = "C:/Users/Roy/Desktop/test/"
Dict = {'hello' : 'good', 'world' : 'bad'}
for dirs, subdirs, files in os.walk(dir):
for file in files:
inFile = codecs.open(dir + file, "r", "utf-8")
inFileStr = inFile.read()
inFile.close()
inFile = codecs.open(dir + file, "w", "utf-8")
for key in Dict:
inFileStr = inFileStr.replace(key, Dict[key])
inFile.write(inFileStr)
inFile.close()
Run Code Online (Sandbox Code Playgroud)
Tho*_*ers 13
在您当前的代码中,您将立即将整个文件读入内存.由于它们是500Mb文件,这意味着500Mb字符串.然后你反复替换它们,这意味着Python必须用第一个替换创建一个新的500Mb字符串,然后销毁第一个字符串,然后为第二个替换创建第二个500Mb字符串,然后销毁第二个字符串,等等,每次更换.事实证明,来回复制数据非常多,更不用说使用大量内存了.
如果您知道替换将始终包含在一行中,您可以通过迭代来逐行读取文件.Python将缓冲读取,这意味着它将得到相当优化.您应该以新名称打开一个新文件,以便同时写入新文件.依次在每一行上执行替换,并立即写出.这样做将大大降低使用的内存量和内存复制来回量为你做的替代品:
for file in files:
fname = os.path.join(dir, file)
inFile = codecs.open(fname, "r", "utf-8")
outFile = codecs.open(fname + ".new", "w", "utf-8")
for line in inFile:
newline = do_replacements_on(line)
outFile.write(newline)
inFile.close()
outFile.close()
os.rename(fname + ".new", fname)
Run Code Online (Sandbox Code Playgroud)
如果你不能确定他们是否总是在一条线上,事情会变得更难一点; 您必须手动读取块,使用inFile.read(blocksize)并仔细跟踪块末尾是否存在部分匹配.不是那么容易,但通常仍然值得避免500Mb字符串.
另一个重大改进是如果你可以一次性完成替换,而不是按顺序尝试一大堆替换.有几种方法可以做到这一点,但最适合的方式完全取决于你要替换的东西和什么.为了将单个字符转换成其他字符translate,unicode对象的方法可能很方便.你传递一个dict映射unicode代码点(作为整数)到unicode字符串:
>>> u"\xff and \ubd23".translate({0xff: u"255", 0xbd23: u"something else"})
u'255 and something else'
Run Code Online (Sandbox Code Playgroud)
要替换子串(而不仅仅是单个字符),您可以使用该re模块.的re.sub函数(和sub编译的正则表达式的方法)可以采用一个可调用(函数)作为第一个参数,然后其将被称为用于每个匹配:
>>> import re
>>> d = {u'spam': u'spam, ham, spam and eggs', u'eggs': u'saussages'}
>>> p = re.compile("|".join(re.escape(k) for k in d))
>>> def repl(m):
... return d[m.group(0)]
...
>>> p.sub(repl, u"spam, vikings, eggs and vikings")
u'spam, ham, spam and eggs, vikings, saussages and vikings'
Run Code Online (Sandbox Code Playgroud)