内存过大的内存错误

2024-04-28 03:54:58 发布

您现在位置:Python中文网/ 问答频道 /正文

我用python编写脚本,现在我必须创建一个非常大的列表,精确地包含248956422个整数。关键是,这个表中的“0”中的一些将被改为1、2或3,因为我有8个列表,4个是基因的起始位置,4个是它们的结尾。 关键是我必须重复“anno”几次,因为替换0的数字可能会随着其他迭代而改变。 “Anno”必须写入文件才能创建注释文件。 这是我的问题,我如何划分,或者动态地进行划分,以避免得到内存错误,包括为其他人替换“0”,为其他人替换1,2,3。 Mabye重写文件?我在等你的建议,请问我是否不清楚我写了什么:P。在

whole_st_gen = [] #to make these lists more clear for example
whole_end_gen = [] # whole_st_gen has element "177" 
whole_st_ex = [] # and whole_end_gen has "200" so from position 177to200
whole_end_ex = [] # i need to put "1"
whole_st_mr = [] # of course these list can have even 1kk+ elements
whole_end_mr = [] # note that every st/end of same kind have equal length
whole_st_nc = [] 
whole_end_nc = [] #these lists are including some values of course
length = 248956422 
anno = ['0' for i in range(0,length)] # here i get the memoryerror
#then i wanted to do something like..
for j in range(0, len(whole_st_gen)):
    for y in range(whole_st_gen[j],whole_end_gen[j]):
        anno[y]='1'

Tags: 文件oftoin列表forrangelength
3条回答

您可以使用bytearray对象来获得比整数列表更紧凑的内存表示:

anno = bytearray(b'\0' * 248956422)
print(anno[0])  # → 0
anno[0] = 2
print(anno[0])  # → 2
print(anno.__sizeof__())  # → 248956447 (on my computer)

我建议使用generator-expression创建一个迭代器,该迭代器可以根据需要生成数字,而不是将它们全部保存在记忆。还有您不需要在循环中使用i,因为它只是一个丢弃的变量,您不需要使用它。在

anno = ('0' for _ in range(0,length)) # In python 2.X use xrange() instead of range() 

但是请注意,and iterator是一个一次性的iterable,在迭代它一个之后就不能使用它时间。如果如果要多次使用它,可以使用itertools.tee()从中创建N独立迭代器。在

另外请注意,如果要根据条件更改某些元素,则不能就地更改它。可以通过迭代迭代器并使用生成器表达式应用条件来创建新的迭代器。在

例如:

^{pr2}$

通过动态确定anno中每个元素的值,可能会更好:

def anno():
    for idx in xrange(248956422):
        elm = "0"

        for j in range(0, len(whole_st_gen)):
            if whole_st_gen[j] <= idx < whole_end_gen[j]:
                elm = "1"                    

        for j in range(0, len(whole_st_ex)):
            if whole_st_ex[j] <= idx < whole_end_ex[j]:
                elm = "2"                    

        for j in range(0, len(whole_st_mr)):
            if whole_st_mr[j] <= idx < whole_end_mr[j]:
                elm = "3"                    

        for j in range(0, len(whole_st_nc)):
            if whole_st_nc[j] <= idx < whole_end_nc[j]:
                elm = "4"                    

        yield elm

然后使用for elm in anno()进行迭代。在

我收到了一份编辑建议,建议对whole_*_genwhole_st_ex等中的每个函数使用一个函数,如下所示:

def anno\u st(): 对于X范围内的idx(248956422): elm=“0”

^{pr2}$

当然,这是可行的,但它只会导致应用whole_*_ex的更改,并且在写入文件时需要合并这些更改,这可能有点尴尬:

for a, b, c, d in zip(anno_st(), anno_ex(), anno_mr(), anno_nc()):
    if d != "0":
        write_to_file(d)
    elif c != "0":
        write_to_file(c)
    elif b != "0":
        write_to_file(b)
    else:
        write_to_file(a)

但是,如果只想应用某些更改集,可以编写一个函数,将它们作为参数:

def anno(*args):
    for idx in xrange(248956422):
        elm = "0"

        for st, end, tag in args:
             for j in range(0, len(st)):
                 if st <= idx < end[j]:
                      elm = tag

        yield tag

然后通过提供列表来调用(例如,只提供前两个更改):

 for tag in anno((whole_st_gen, whole_end_gen, "1"),
                 (whole_st_ex, whole_end_ex, "2")):
     write_to_file(tag)

相关问题 更多 >