所以我在python中有这个代码,它将一些值写入一个Dictionary,其中每个键都是一个学生ID号,每个值都是一个Class(类型为student),其中每个Class都有一些与之关联的变量。 “
try:
if ((str(i) in row_num_id.iterkeys()) and (row_num_id[str(i)]==varschosen[1])):
valuetowrite=str(row[i])
if students[str(variablekey)].var2 != []:
students[str(variablekey)].var2.append(valuetowrite)
else:
students[str(variablekey)].var2=([valuetowrite])
except:
two=1#This is just a dummy assignment because I #can't leave it empty... I don't need my program to do anything if the "try" doesn't work. I just want to prevent a crash.
#Assign var3
try:
if ((str(i) in row_num_id.iterkeys()) and (row_num_id[str(i)]==varschosen[2])):
valuetowrite=str(row[i])
if students[str(variablekey)].var3 != []:
students[str(variablekey)].var3.append(valuetowrite)
else:
students[str(variablekey)].var3=([valuetowrite])
except:
two=1
#Assign var4
try:
if ((str(i) in row_num_id.iterkeys()) and (row_num_id[str(i)]==varschosen[3])):
valuetowrite=str(row[i])
if students[str(variablekey)].var4 != []:
students[str(variablekey)].var4.append(valuetowrite)
else:
students[str(variablekey)].var4=([valuetowrite])
except:
two=1
对于学生拥有的每个变量(var5,var6,...... varX),相同的代码会重复多次。但是,当我执行执行这一系列变量赋值的函数时,程序中的RAM峰值出现了。
我希望找到一种方法来提高速度或提高内存效率,因为运行我程序的这一部分需要大约半个内存。 :(
感谢您的帮助!
编辑:
好的,让我简化一下我的问题: 在我的例子中,我有一个大约6000个实例化类的字典,其中每个类有1000个属性变量,所有类型字符串或字符串列表。我真的不关心我的代码行数或运行速度(现在,我的代码大约是20,000行,大约是1 MB .py文件!)。我关心的是它占用的内存量,因为这是限制我的CPU的罪魁祸首。最终的问题是:我构建这个庞大的字典的代码行数在RAM使用方面是否如此重要?
我的原始代码运行正常,但RAM使用率很高。我不确定这与我收集的数据量是否“正常”。以简洁的方式编写代码(如下面帮助过我的人所示)实际上会使我吃掉的内存量明显不同吗?当然有X方法来构建字典,但在这种情况下它是否会影响RAM的使用?
答案 0 :(得分:3)
编辑:下面建议的代码重构不会大幅减少内存消耗。每个有1000个属性的6000个类可能会消耗半个内存。
最好将数据存储在数据库中,并仅在需要时通过SQL查询提取数据。或者您可以使用shelve或marshal将部分或全部数据转储到磁盘,只有在需要时才能将其读回。第三种选择是使用numpy字符串数组。 numpy数组将更紧凑地保持字符串。 (Python字符串是具有许多方法的对象,这些方法使得它们在内存方面更加庞大。一个字符串的数组丢失了所有这些方法但需要相对较少的内存开销。)第四个选项可能是使用PyTables。
最后(但并非最不重要),可能有方法重新设计您的算法,以减少内存密集。我们必须更多地了解您的计划以及它试图解决的问题,以提供更具体的建议。
原创建议:
for v in ('var2','var3','var4'):
try:
if row_num_id.get(str(i))==varschosen[1]:
valuetowrite=str(row[i])
value=getattr(students[str(variablekey)],v)
if value != []:
value.append(valuetowrite)
else:
value=[valuetowrite]
except PUT_AN_EXPLICT_EXCEPTION_HERE:
pass
PUT_AN_EXPLICT_EXCEPTION_HERE
应替换为AttributeError
或TypeError
或ValueError
等内容,或者其他内容。
很难猜测放在这里的内容因为我不知道变量可能具有什么样的值。
如果您运行没有try...exception
块的代码,并且程序崩溃,请记下您收到的回溯错误消息。最后一行会说
TypeError: ...
在这种情况下,请将PUT_AN_EXPLICT_EXCEPTION_HERE
替换为TypeError
。
如果您的代码可能会以多种方式失败,例如TypeError
或ValueError
,那么您可以将PUT_AN_EXPLICT_EXCEPTION_HERE
替换为
(TypeError,ValueError)
可以捕获这两种错误。
注意:应该提及一些技术性的警告
row_num_id.get(str(i))==varschosen[1]
。如果row_num_id.get(str(i))
不在None
中,则str(i)
表达式会返回row_num_id
。
但是如果varschosen[1]
None
和str(i)
不在row_num_id
,该怎么办?然后条件为True
,当较长的原始条件返回False
时。
如果可能,那么解决方案是使用像row_num_id.get(str(i),object())==varschosen[1]
这样的sentinal默认值。当row_num_id.get(str(i),object())
不在object()
时,str(i)
会立即返回row_num_id
。由于object()
是object
的新实例,因此无法与varschosen[1]
相等。
答案 1 :(得分:0)
你拼写错了
two=1#This is just a dummy assignment because I
#can't leave it empty... I don't need my program to do anything if the "try" doesn't work. I just want to prevent a crash.
拼写
pass
您应该阅读有关Python的教程。
此外,
except:
是一个糟糕的政策。当程序崩溃时,你的程序将无法崩溃。
var2
和var3
等名称是邪恶的。他们故意误导。
不要一遍又一遍地重复str(variablekey)
。
我希望找到一种方法来提高速度或提高内存效率,因为运行我程序的这一部分需要大约半个内存。 :(
这个请求是无法回答的,因为我们不知道它应该做什么。像var1
和var2
这样的故意模糊名称使其无法理解。
答案 2 :(得分:0)
“6000个实例化类,其中每个类有1000个属性变量”
因此。 600万件物品?这是很多记忆。真的很多记忆。
我关注的是它占用的内存量,因为这是限制我的CPU的罪魁祸首
真的?有证据吗?
但RAM使用率很高
与什么相比?这个主张的基础是什么?
答案 3 :(得分:0)
Python dicts使用了大量的内存。尝试:
import sys
for i in range( 30 ):
d = dict( ( j, j ) for j in range( i ) )
print "dict with", i, "elements is", sys.getsizeof( d ), "bytes"
以说明它们有多贵。请注意,这只是dict本身的大小:它不包括存储在dict中的键或值的大小。
默认情况下,Python类的实例将其属性存储在dict中。因此,您的6000个实例中的每个实例都在为该字典使用大量内存。
如果您的实例都具有相同的属性集,则可以节省大量内存的一种方法是使用__slots__
(请参阅http://docs.python.org/reference/datamodel.html#slots)。例如:
class Foo( object ):
__slots__ = ( 'a', 'b', 'c' )
现在,类Foo的实例为三个属性a
,b
和c
分配了空间,但没有实例dict存储任何其他属性。每个属性只使用4个字节(在32位系统上),而使用dict的每个属性可能只有15-20个字节。
另一种可能浪费内存的方法,假设你有很多字符串,那就是你要存储同一个字符串的多个相同副本。如果这是一个问题,使用intern
函数(请参阅http://docs.python.org/library/functions.html#intern)可能会有所帮助。