Python 每次都从文件中读取还是将值存储在列表中?
Python read from file every time or store values in list?
我目前正在编写一个 python 脚本来通过暴力生成每个素数。我目前有一个大于 5Mb 的文件,其中包含质数,并且作为脚本 运行s,它会附加它找到的任何新质数,因此文件会不断变大。每次脚本是 运行 时,这个文件都会被读入一个列表,然后循环计算下一个数字是否是素数,任何新的素数也会被附加到这个列表中。
我的问题是,是每次脚本 运行 时将此文件加载到内存中更好,还是我应该在 for 循环中读取文件的下一行,根据数字进行处理检查,然后加载下一行?
前者创建一个保存在内存中的大列表,但速度非常快,第二个会更慢,因为每次循环迭代时它都必须读取文件,但我认为它不会在内存附近使用。
这是我的代码,它将一个配置文件作为参数,其中包含开始寻找质数的数字,文件 read/write 质数为:
import sys, math, time
def is_prime(num,primes):
square = math.floor(math.sqrt(num))
print('using all prime numbers up to %d' % square)
for p in primes:
if p <= square:
print (p, end='\r')
if (num % p) == 0:
return False
else:
return True
return True
def main(argv):
if len(sys.argv) == 2:
try:
try:
f = open(sys.argv[1], 'r+')
except IOError:
sys.exit('Error: File %s does not exist in the current directory...\nUsage: generate_primes.py <prime_file>' % sys.argv[1])
f.close()
f = open(sys.argv[1], 'r+')
low = f.readlines()
f.close()
num_to_check = int(low[0].strip('\n'))
file_name = low[1].strip('\n')
print(num_to_check)
print(file_name)
if num_to_check % 2 == 0:
num_to_check += 1
f = open(file_name, 'a+')
f.seek(0)
primes = f.readlines()
print('Processing Primes...')
for key,i in enumerate(primes):
primes[key] = int(primes[key].strip('\n'))
if primes[-1] > num_to_check:
num_to_check = primes[-1]
print('Last saved prime is bigger than config value.\nDefaulting to largest saved prime... %d' % primes[-1])
time.sleep(2)
new_primes = 0
while True:
print('Checking: %s ' % str(num_to_check), end='')
if is_prime(num_to_check,primes):
print('Prime')
f.write('%s\n' % str(num_to_check))
primes.append(num_to_check)
new_primes += 1
else:
print('Composite')
num_to_check += 2
except KeyboardInterrupt:
config_name = time.strftime('%Y%m%d-%H%M%S')
print('Keyboard Interrupt: \n creating config file %s ... ' % config_name)
c = open(config_name,'w')
c.write('%d\n%s' % (num_to_check,file_name))
c.close()
f.close()
print('Done\nPrimes Found: %d\nExiting...' % new_primes)
sys.exit()
if __name__ == '__main__':
main(sys.argv[1:])
注意:素数文件不能包含单独的 1 否则每个数字都会成为合数。
关于只从文件中读取的一个问题是能够获取存储的最大素数的值(也就是读取文件中的最后一行)。
速度和内存的优化常常是矛盾的。一些程序会使用大量内存,但速度非常快(Chrome 力争做到这一点),其他程序可能会相反,许多人试图在两者之间寻求平衡。选择关注的重点应该主要围绕问题、用例,如果你真的很透彻,还应该围绕数据。
如果脚本要一遍又一遍地 运行,延迟和慢速加起来真的会很快......您可能需要专注于优化速度。如果脚本花费超过一秒左右的时间 运行 并且用户必须无用地盯着屏幕直到它完成才能继续……您可能需要关注速度。如果您的操作对时间很敏感,也许事情需要实时发生,并且您不想因过多的延迟而落后......您可能需要关注速度。
如果脚本只是偶尔 运行,并且在主要对时间不敏感的环境中,最好是在后台某处,尤其是在有限或低端硬件上...您可能需要关注在记忆中。
更具体地说明您的问题,我可以说我完全同意 Kristjan 的评论,5MB 并不算多。现在看看我笔记本电脑上的任务管理器,我可以说我从维基百科打开了两个标签,很长时间没碰过它们,他们使用的是 33 倍,Facebook 上的一个标签,类似的故事,但 280 倍, rubyMine (IDE) 使用的是 244 倍,activity monitor(Task Manager) 本身使用的是 33 倍,在 20MB 标记下并没有发生太多事情,除了小系统的东西,这些东西真的应该以更少的成本组合在一起杂乱无章,有些程序我以为我一周前就关闭了。如果您的应用程序的其余部分保持相对较低的内存占用,您不是针对弱硬件或嵌入式硬件,那么人们可能会很快抱怨速度慢而不是 RAM 中约 5MB 的占用空间,特别是如果您在您的 RAM 中清理它完成(更适用于低级语言,但也许 del
可以帮助这里)。
但实际上,只有您知道您正在处理的问题的局限性。好吧,这可能不是真的,但我当然不认识他们。您将不得不就在您的实施中对您来说重要的事情做出决定,这可能涉及到某个地方的妥协。对两种实现进行基准测试以量化速度的提高可能会帮助您证明一个决定优于另一个,并且在平局中,当然也可以考虑实施的便利性。
我目前正在编写一个 python 脚本来通过暴力生成每个素数。我目前有一个大于 5Mb 的文件,其中包含质数,并且作为脚本 运行s,它会附加它找到的任何新质数,因此文件会不断变大。每次脚本是 运行 时,这个文件都会被读入一个列表,然后循环计算下一个数字是否是素数,任何新的素数也会被附加到这个列表中。
我的问题是,是每次脚本 运行 时将此文件加载到内存中更好,还是我应该在 for 循环中读取文件的下一行,根据数字进行处理检查,然后加载下一行?
前者创建一个保存在内存中的大列表,但速度非常快,第二个会更慢,因为每次循环迭代时它都必须读取文件,但我认为它不会在内存附近使用。
这是我的代码,它将一个配置文件作为参数,其中包含开始寻找质数的数字,文件 read/write 质数为:
import sys, math, time
def is_prime(num,primes):
square = math.floor(math.sqrt(num))
print('using all prime numbers up to %d' % square)
for p in primes:
if p <= square:
print (p, end='\r')
if (num % p) == 0:
return False
else:
return True
return True
def main(argv):
if len(sys.argv) == 2:
try:
try:
f = open(sys.argv[1], 'r+')
except IOError:
sys.exit('Error: File %s does not exist in the current directory...\nUsage: generate_primes.py <prime_file>' % sys.argv[1])
f.close()
f = open(sys.argv[1], 'r+')
low = f.readlines()
f.close()
num_to_check = int(low[0].strip('\n'))
file_name = low[1].strip('\n')
print(num_to_check)
print(file_name)
if num_to_check % 2 == 0:
num_to_check += 1
f = open(file_name, 'a+')
f.seek(0)
primes = f.readlines()
print('Processing Primes...')
for key,i in enumerate(primes):
primes[key] = int(primes[key].strip('\n'))
if primes[-1] > num_to_check:
num_to_check = primes[-1]
print('Last saved prime is bigger than config value.\nDefaulting to largest saved prime... %d' % primes[-1])
time.sleep(2)
new_primes = 0
while True:
print('Checking: %s ' % str(num_to_check), end='')
if is_prime(num_to_check,primes):
print('Prime')
f.write('%s\n' % str(num_to_check))
primes.append(num_to_check)
new_primes += 1
else:
print('Composite')
num_to_check += 2
except KeyboardInterrupt:
config_name = time.strftime('%Y%m%d-%H%M%S')
print('Keyboard Interrupt: \n creating config file %s ... ' % config_name)
c = open(config_name,'w')
c.write('%d\n%s' % (num_to_check,file_name))
c.close()
f.close()
print('Done\nPrimes Found: %d\nExiting...' % new_primes)
sys.exit()
if __name__ == '__main__':
main(sys.argv[1:])
注意:素数文件不能包含单独的 1 否则每个数字都会成为合数。
关于只从文件中读取的一个问题是能够获取存储的最大素数的值(也就是读取文件中的最后一行)。
速度和内存的优化常常是矛盾的。一些程序会使用大量内存,但速度非常快(Chrome 力争做到这一点),其他程序可能会相反,许多人试图在两者之间寻求平衡。选择关注的重点应该主要围绕问题、用例,如果你真的很透彻,还应该围绕数据。
如果脚本要一遍又一遍地 运行,延迟和慢速加起来真的会很快......您可能需要专注于优化速度。如果脚本花费超过一秒左右的时间 运行 并且用户必须无用地盯着屏幕直到它完成才能继续……您可能需要关注速度。如果您的操作对时间很敏感,也许事情需要实时发生,并且您不想因过多的延迟而落后......您可能需要关注速度。
如果脚本只是偶尔 运行,并且在主要对时间不敏感的环境中,最好是在后台某处,尤其是在有限或低端硬件上...您可能需要关注在记忆中。
更具体地说明您的问题,我可以说我完全同意 Kristjan 的评论,5MB 并不算多。现在看看我笔记本电脑上的任务管理器,我可以说我从维基百科打开了两个标签,很长时间没碰过它们,他们使用的是 33 倍,Facebook 上的一个标签,类似的故事,但 280 倍, rubyMine (IDE) 使用的是 244 倍,activity monitor(Task Manager) 本身使用的是 33 倍,在 20MB 标记下并没有发生太多事情,除了小系统的东西,这些东西真的应该以更少的成本组合在一起杂乱无章,有些程序我以为我一周前就关闭了。如果您的应用程序的其余部分保持相对较低的内存占用,您不是针对弱硬件或嵌入式硬件,那么人们可能会很快抱怨速度慢而不是 RAM 中约 5MB 的占用空间,特别是如果您在您的 RAM 中清理它完成(更适用于低级语言,但也许 del
可以帮助这里)。
但实际上,只有您知道您正在处理的问题的局限性。好吧,这可能不是真的,但我当然不认识他们。您将不得不就在您的实施中对您来说重要的事情做出决定,这可能涉及到某个地方的妥协。对两种实现进行基准测试以量化速度的提高可能会帮助您证明一个决定优于另一个,并且在平局中,当然也可以考虑实施的便利性。