Python 3.5 与 2.7 之间字符串连接的巨大时间差异
Posted
技术标签:
【中文标题】Python 3.5 与 2.7 之间字符串连接的巨大时间差异【英文标题】:Huge timing difference in string concatenation between Python 3.5 vs 2.7 【发布时间】:2018-10-09 14:29:03 【问题描述】:我有 340,000 行文件数据,当我用 Python 3.5 读取文件时,时间很好,但是当我用 Python 2.7 运行它时,读取速度很慢,不知道这里发生了什么,这里是代码:
import codecs as cds
INPUT_DATA_DIR = 'some_tsv_file.tsv'
ENT = "entities"
def train_data_getter(input_dir=INPUT_DATA_DIR):
file_h = cds.open(input_dir, encoding='utf-8')
data = file_h.read()
file_h.close()
sentences = data.split("\n\n")
parsed_data = parser(sentences[0])
return parsed_data
def parser(raw_data):
words = [line for line in raw_data.split("\n")]
temp_l = []
temp_s = ""
for word in words:
token, ent = word.split('\t')
temp_s += token
temp_s += " "
temp_l.append(ent)
data = [(temp_s), ENT: temp_l]
return data
编辑
感谢@PM 2Ring,问题是 for 循环内的字符串连接,但我仍然不清楚 Python2.7 和 3.5 之间存在巨大差异的原因。
【问题讨论】:
哪里慢了?您可能会问自己,这里可能有哪些昂贵的操作,并花一些时间来弄清楚究竟是哪些函数调用在 2.7 中减慢了您的程序。 这可能对速度差异影响不大,但在循环中进行字符串连接并不是一个好主意。因此,更改temp_s
的内容以将字符串累积到一个列表中(就像您对 temp_l
所做的那样),然后在循环结束时将 .join
列表变成一个字符串。
@PM2Ring:我认为这可能对速度差异有很多的影响! (各种 Python 版本都有 hack,可以防止特定常见形式的重复连接具有二次运行时间;不过,我不记得在哪个版本中引入了 hack。)
@Arman 我不确定,但 Python 3 在各个方面都做了很多改进,包括对常见字符串操作的一些优化。但是,Python 2.7 已经 对短字符串的连接进行了一些优化。尝试在 Python 2 的早期版本上运行该代码,您将真正看到速度大幅下降。 :)
@MarkDickinson 我也不确定,但我知道在 Python 3 之前已经在这个方向上进行了一些优化;我记得 Alex Martelli 不很高兴:请参阅 ***.com/a/1350289/4014959
【参考方案1】:
您在循环中迭代地追加 340,000 次效率非常低,所以不要这样做。
无论如何,pandas supports tsv read,它会更高效,并且支持chunksize
参数用于快速读取大型 csv/tsv 文件:
import pandas
train = pd.read_table('some_tsv_file.tsv', delim_whitespace=True, chunksize=100000)
# you probably need encoding='utf-8'. You may also need to tweak the settings for header, skiprows etc. Read the doc.
【讨论】:
感谢您的回答,由于时间问题已解决,请不要执行字符串 concat,我的主要问题是 Python 之间的这种差异。 Arman,只需安装 pandas 并运行 pd.read_table/csv 即可。速度差异应该让你吃惊。你永远不应该依赖解释器来优化效率低下的代码。以上是关于Python 3.5 与 2.7 之间字符串连接的巨大时间差异的主要内容,如果未能解决你的问题,请参考以下文章
在 Mac OS X 上的 python 2.7 和 python 3.5 之间切换