Python中随机文本w / r的更快解决方案

时间:2013-11-13 11:30:23

标签: python randomaccessfile

我需要一个快速的解决方案,用于Python中随机w / r的文本片段。我想做的是这样的:

  1. 编写代码段并记录指针
  2. 使用指针检索代码段
  3. 片段是任意长度的,我选择不使用数据库来存储它们,而只选择指针。通过简单地用C函数替换Python文件方法(解决方案1),它的速度非常快,指针只包含片段的“where”和“多长时间”。之后,我尝试了我认为与Berkeley DB一起使用的真实内容。我不知道该怎么称呼它,也许是“寻呼”的东西?

    问题是,这个代码绝对有效,比解决方案1快1.5到2倍,但速度并不快,需要使用4部分指针。 也许这不是一个有价值的方法,但是有没有空间来显着改善它?

    以下是代码:

    from collections import namedtuple
    from ctypes import cdll,c_char_p,\
         c_void_p,c_size_t,c_long,\
         c_int,create_string_buffer
    libc = cdll.msvcrt
    fopen = libc.fopen
    fread = libc.fread
    fwrite = libc.fwrite
    fseek = libc.fseek
    ftell = libc.ftell
    fflush = libc.fflush
    fclose = libc.fclose
    
    #######################################################
    # The following is how to write a snippet into the SnippetBase file
    
    ptr = namedtuple('pointer','blk1, start, nblk, length')
    snippet = '''
    blk1: the first blk where the snippet is
    start: the start of this snippet
    nblk: number of blocks this snippet takes
    length: length of this snippet
    '''
    bsize = 4096 # bsize: block size
    
    fh = fopen('.\\SnippetBase.txt','wb')
    fseek(fh,0,2)
    pos1 = divmod(ftell(fh),bsize)
    fwrite(snippet,c_size_t(len(snippet)),1,fh)
    fflush(fh)
    pos2 = divmod(ftell(fh),bsize)
    ptr = ptr(pos1[0],pos1[1],pos2[0]-pos1[0]+1,len(snippet))
    fclose(fh)
    
    
    #######################################################
    # The following is how to read the snippet from the SnippetBase file
    
    fh = fopen('.\\SnippetBase.txt','rb')
    fseek(fh,c_long(ptr.blk1*bsize),1)
    buff = create_string_buffer(ptr.nblk*bsize)
    fread(buff,c_size_t(ptr.nblk*bsize),1,fh)
    print buffer(buff,ptr.start,ptr.length)
    fclose(fh)
    

1 个答案:

答案 0 :(得分:1)

这看起来像是一种硬性且不可移植的方法来优化一件事 - 由Python包装器file.reados.read执行的内存分配。所有其他部分都可以使用Python标准库中现有的函数轻松完成。甚至有一种简单的方法可以在bytearray中分配读/写缓冲区。 io模块确实包含方法readinto,该方法存在于文件类型中;我非常怀疑这确实避免了分配。在最流行的操作系统上,我们可以更进一步 - 通过直接使用OS磁盘缓冲区而不是为我们的进程本地分配内存。这是使用mmap完成的(但是当文件太大而无法放入地址空间时,使用它会变得很棘手)。对于从mmaped文件中读取数据的非分配方法,只需使用buffer(mm, offset, size)