2010-08-02 67 views
2

所以我在Python中有这样的代码,它将一些值写入字典,其中每个键都是学生ID号,每个值都是一个Class(学生类),其中每个Class都有一些与其相关的变量。 '这个Python代码可以更有效地写入吗?

代码
 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

使用4个空格而不是制表符(特别是粘贴代码时)。大多数优秀的编辑可以默认为你做这个。还可以使用“pass”而不是'two = 1' – 2010-08-02 21:01:26

+0

一些注意事项:使用'except Exception',而不是'two = 1'使用'pass'。 – 2010-08-02 21:02:27

回答

3

编辑:下面的建议代码重构不会很大程度上减少内存消耗。每个1000个属性的6000个类可能会消耗半个内存。

将数据存储在数据库中并仅在需要时通过SQL查询提取数据可能会更好。或者,您可以使用shelvemarshal将部分或全部数据转储到磁盘,只有在需要时才可以将其读回。第三种选择是使用一个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应该像AttributeErrorTypeError,或ValueError,也许别的东西来代替。 很难猜出要放在这里,因为我不知道变量可能具有什么样的值。

如果您运行的代码没有try...exception块,并且程序崩溃,请记下您收到的回溯错误消息。最后一行会这样说

TypeError: ...

在这种情况下,与TypeError更换PUT_AN_EXPLICT_EXCEPTION_HERE

如果你的代码可以在许多方面失败了,说,与TypeErrorValueError,那么你就可以代替PUT_AN_EXPLICT_EXCEPTION_HERE(TypeError,ValueError)赶上这两种错误的。

注意:关于 row_num_id.get(str(i))==varschosen[1]应该提及一点技术警告。如果str(i)不在row_num_id中,则表达式row_num_id.get(str(i))返回None。 但是如果varschosen[1]Nonestr(i)不在row_num_id?那么条件是True,当较长的原始条件返回False

如果这是一种可能性,那么解决方案是使用一个默认值,如row_num_id.get(str(i),object())==varschosen[1]。当str(i)不在row_num_id中时,现在row_num_id.get(str(i),object())返回object()。由于object()object的新实例,因此无法等于varschosen[1]

+0

在'if'语句中的条件可以更紧凑地写入'row_num_id.get(str(i))== varschosen [1]' – 2010-08-02 21:08:53

+0

@David:谢谢你的想法。我会编辑我的帖子... – unutbu 2010-08-02 21:14:13

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: 

是一个糟糕的政策。当它应该崩溃时,你的程序将无法崩溃。

var2var3这样的名字是邪恶的。他们故意误导人。

不要重复str(variablekey)一遍又一遍。

我希望找到一种方法来提高速度或提高内存使用效率,因为运行这部分程序需要大约半个内存。 :(

此请求是无法回答的,因为我们不知道它应该做什么。故意晦涩难懂的名字如var1var2使其无法理解。

+0

嗨,谢谢你的建议....变量标签故意留下含糊不清,因为我正在处理的数据类型要被读入和分析。他们的标签/含义是用户定义的,因此不能被硬编码。 – Brian 2010-08-02 21:27:47

+0

@Brian:请更新您的问题,提供一些关于您正在做什么的提示。 “他们的标签/含义是用户定义的”没有理由被故意误导。 – 2010-08-02 22:20:14

+0

问题更新.... – Brian 2010-08-02 23:20:29

0

“6000个实例化类,每个类有1000归结变量”

所以。 600万个物体?这是很多的记忆。一个真正的记忆。

我所关心的是内存量是占用了,因为这是我的节流CPU

真正的罪魁祸首?有证据吗?

但RAM使用率很高

什么比较?这种说法的基础是什么?

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" 

为了说明它们有多昂贵。请注意,这只是字典本身的大小:它不包括存储在字典中的键或值的大小。

默认情况下,Python类的实例将其属性存储在字典中。因此,您的每个6000实例都只使用大量的内存来存储该字典。

如果您的实例都具有相同的一组属性,则可以节省大量内存的一种方法是使用__slots__(请参阅http://docs.python.org/reference/datamodel.html#slots)。例如:

class Foo(object): 
    __slots__ = ('a', 'b', 'c') 

现在,Foo类的实例有正好三个属性,abc空间分配,但没有实例字典中存储的其他属性。每个属性只使用4个字节(在32位系统上),而每个属性使用一个字典可能只有15-20个字节。

考虑到您有很多字符串,您可能会浪费内存的另一种方式是如果您要存储同一字符串的多个相同副本。如果事实证明这是一个问题,使用intern函数(请参阅http://docs.python.org/library/functions.html#intern)可能会有所帮助。