2

我有 python 脚本来过滤 csv 文件中的大量数据。该要求要求考虑在运行时间和内存使用方面的可扩展性。

我写了 2 个脚本,它们都可以很好地过滤数据。关于考虑可扩展性,我决定使用 python 生成器,因为它使用迭代器并且不会在内存中保存太多数据。

当我比较了 2 个脚本的运行时间时,我发现如下:

脚本 1 - 使用生成器 - 花费更多时间 - 0.0155925750732s

def each_sentence(text):
    match = re.match(r'[0-9]+', text)
    num = int(text[match.start():match.end()])
    if sympy.isprime(num) == False:
        yield text.strip()

with open("./file_testing.csv") as csvfile:
    for line in csvfile:
        for text in each_sentence(line):
            print(text)

脚本 2 - 使用拆分且不使用生成器 - 花费更少的时间 - 0.00619888305664

with open("./file_testing.csv") as csvfile:
for line in csvfile:
    array = line.split(',')
    num = int(array[0])
    if sympy.isprime(num) == False:
        print line.strip()

为了满足要求,我需要使用python生成器吗?或任何建议或建议?

4

2 回答 2

1

为了满足要求,我需要使用python生成器吗?

不,你没有。脚本 1 没有意义。生成器总是执行一次,并在第一次迭代中返回一个结果。

有什么建议或建议吗?

您需要了解三件事:复杂性、并行化和缓存。

  • 复杂性基本上意味着“如果我将输入数据(csv 文件)的大小增加一倍,我需要两倍的时间吗?还是四倍?还是什么”?

  • 并行化意味着以一种可以轻松添加更多资源来解决问题的方式来解决问题。

  • 缓存很重要。如果您不必一直重新创建所有内容,事情会变得更快,但是您可以重新使用已经生成的内容。

除非 csv 文件包含极长的行,否则主循环for line in csvfile:已经可以很好地扩展。

脚本 2 包含一个错误:如果一行中的第一个单元格不是整数,int(array[0])则会引发值错误。

isprime函数可能是您代码中的“热点”,因此您可以尝试将其与多个线程或子进程并行化。

于 2019-02-27T05:01:48.813 回答
1

将您的分析拆分为两个离散的正则表达式结果:一个包含 10 个值的小结果,一个包含 10,000,000 个值的大结果。这个问题与 的平均值len()有关match,与的平均值len()有关csvfile

re 结果很小 - 10 个字节

第一个代码块将具有较慢的运行时间和相对较低的内存使用率

第二个代码块将具有更快的运行时间,并且内存使用率也相对较低

具有大的重新结果 - 10,000,000 字节

第一个代码块的运行时间较慢,内存使用量也很少。

第二个代码块将具有更快的运行时间和非常大的内存使用量。

底线:

如果您应该构建一个考虑运行时间和内存的函数,那么当问题需要针对不同结果大小的可扩展解决方案时,yield 函数绝对是最好的方法。

关于可扩展性的另一个问题:如果 re 结果等于 None 怎么办?我会稍微修改代码如下:

def each_sentence(text):
    match = re.match(r'[0-9]+', text)
    if match != None:
        num = int(text[match.start():match.end()])
        if sympy.isprime(num) == False:
            yield text.strip()

with open("./file_testing.csv") as csvfile:
    for line in csvfile:
        for text in each_sentence(line):
            print(text)
于 2019-02-27T05:03:44.453 回答