Python 随机访问文件
Posted
技术标签:
【中文标题】Python 随机访问文件【英文标题】:Python Random Access File 【发布时间】:2011-02-15 02:18:30 【问题描述】:是否有一种 Python 文件类型可以在不遍历整个文件的情况下访问随机行?我需要在一个大文件中搜索,不可能将整个内容读入内存。
任何类型或方法都将不胜感激。
【问题讨论】:
您能解释一下为什么要读取随机行,而不是部分读取整个文件。 在文件中进行二进制搜索,因为每一行都以整数开头。我想将整数视为键,将行的其余部分视为值。 【参考方案1】:这似乎正是mmap
的设计目的。 mmap
对象为文件创建了一个类似字符串的接口:
>>> f = open("bonnie.txt", "wb")
>>> f.write("My Bonnie lies over the ocean.")
>>> f.close()
>>> f.open("bonnie.txt", "r+b")
>>> mm = mmap(f.fileno(), 0)
>>> print mm[3:9]
Bonnie
如果您想知道,mmap
对象也可以分配给:
>>> print mm[24:]
ocean.
>>> mm[24:] = "sea. "
>>> print mm[:]
My Bonnie lies over the sea.
【讨论】:
但是 mmap 不也将整个文件加载到内存中吗? ` mm = mmap(f.fileno(), 0)` 是(据我了解)将整个文件读入内存。你能详细说明一下吗? @Oleg 我的理解是它没有。相反,它通过虚拟内存机制使硬盘驱动器像 RAM 一样可寻址。我不知道所有细节,但它绝对不会一开始就将整个文件加载到内存中,就像***上的 Mmap 文章 explains。【参考方案2】:你可以使用linecache:
import linecache
print linecache.getline(your_file.txt, randomLineNumber) # Note: first line is 1, not 0
【讨论】:
这太酷了!它是一个内置的 Python 模块!谢谢!【参考方案3】:由于行可以是任意长度,如果不遍历,您真的无法获得随机行(无论您的意思是“编号实际上是随机的行”还是“由我选择的任意编号的行”)整个文件。
如果 kinda-sorta-random 就足够了,您可以在文件中寻找一个随机位置,然后向前读取,直到遇到行终止符。但是,如果您想找到(例如)第 1234 行,那将毫无用处,并且如果您确实想要随机选择的行,则会对行进行非均匀采样。
【讨论】:
我看到你想做一个二分搜索。在这种情况下:是的,寻找大约在当前下限和上限之间的中间点,读取一个块,然后在该块中查找行。 (这可能很明显,但是:除非它们很长,否则不要尝试在各个行的粒度上随机搜索。阅读更大的部分。这样你就更少依赖操作系统和 Python 缓冲的细节,并且您避免了一些开销。)【参考方案4】:文件对象有一个 seek 方法,它可以为该文件中的特定字节获取一个值。 为了遍历大文件,遍历它并检查每一行中的值。迭代文件对象不会将整个文件内容加载到内存中。
【讨论】:
【参考方案5】:是的,您可以轻松获得随机线。只需寻找文件中的随机位置,然后寻找开头,直到您点击 \n 或文件的开头,然后读取一行。
代码:
import sys,random
with open(sys.argv[1],"r") as f:
f.seek(0,2) # seek to end of file
bytes = f.tell()
f.seek(int(bytes*random.random()))
# Now seek forward until beginning of file or we get a \n
while True:
f.seek(-2,1)
ch = f.read(1)
if ch=='\n': break
if f.tell()==1: break
# Now get a line
print f.readline()
【讨论】:
一些笔记。 (1) 如果您要在其中四处寻找,您可能应该将其作为二进制文件打开。 (2) 如果您从着陆点向前看而不是向后看,您可能会获得更好的性能(因为与底层缓冲的交互更好,并且对 f.seek 的调用更少)。这样做的缺点是您永远不会以这种方式获得第一行,并且可能会到达文件的末尾,但是您可以通过以下方式解决这个问题:如果您到达文件的末尾,请转到开头并阅读从那里有一条线。 是的。前进的性能会稍高一些,但随后您需要环绕逻辑。我的大部分开发都是在 Unix 上进行的,“二进制”和“文本”文件之间的区别没有意义。【参考方案6】:File 对象支持查找,但请确保以二进制形式打开它们,即“rb”。
您可能还希望使用 mmap 模块进行随机访问,尤其是在数据已经是内部格式的情况下。
【讨论】:
【参考方案7】:有固定长度的记录吗?如果是这样,是的,您可以使用 seek 实现二进制搜索算法。
否则,将您的文件加载到 SQLlite 数据库中。查询那个。
【讨论】:
以上是关于Python 随机访问文件的主要内容,如果未能解决你的问题,请参考以下文章