如何从python中的一个文件中读取随机行?

时间:2010-08-22 05:23:48

标签: python

是否有内置方法可以做到这一点?如果不能,如何在不花费太多开销的情况下做到这一点?

12 个答案:

答案 0 :(得分:60)

不是内置的,但Knuth的“计算机编程艺术”中的算法R(3.4.2)(Waterman的“水库算法”)很好(在一个非常简化的版本中):

import random

def random_line(afile):
    line = next(afile)
    for num, aline in enumerate(afile, 2):
      if random.randrange(num): continue
      line = aline
    return line

num, ... in enumerate(..., 2)迭代器生成序列2,3,4 ...因此randrange将为0,概率为1.0/num - 这就是我们必须的概率替换当前选择的行(参考算法的样本大小1的特殊情况 - 请参阅Knuth的书以获得正确性证明==当然我们也是在一个足够小的“库”的情况下适合记忆; - ))......以及我们的概率。

答案 1 :(得分:27)

import random
lines = open('file.txt').read().splitlines()
myline =random.choice(lines)
print(myline)

对于很长的文件: 根据它的长度寻找文件中的随机位置,并在位置(或换行符和文件结尾)之后找到两个换行符。如果原始搜索位置<100,如果我们在最后一行内部结束,则在文件开头之前或之后再做100个字符。

然而这很复杂,因为文件是iterator.So使它列出并取random.choice(如果你需要很多,请使用random.sample):

import random
print(random.choice(list(open('file.txt'))))

答案 2 :(得分:9)

这取决于“太多”开销是什么意思。如果可以将整个文件存储在内存中,那么就像

import random

random_lines = random.choice(open("file").readlines())

会做到这一点。

答案 3 :(得分:9)

虽然我迟到了四年,但我认为我有最快的解决方案。最近我写了一个名为linereader的python包,它允许你操作文件句柄的指针。

以下是使用此软件包获取随机行的简单解决方案:

from random import randint
from linereader import dopen

length = #lines in file
filename = #directory of file

file = dopen(filename)
random_line = file.getline(randint(1, length))

第一次这样做是最糟糕的,因为linereader必须以特殊格式编译输出文件。完成此操作后,无论文件大小如何,linereader都可以快速访问文件中的任何行。

如果您的文件非常小(小到足以容纳MB),那么您可以用dopen替换copen,并在内存中生成文件的缓存条目。这不仅更快,而且在文件加载到内存时获得文件内的行数;它是为你完成的。您需要做的就是生成随机行号。以下是一些示例代码。

from random import randint
from linereader import copen

file = copen(filename)
lines = file.count('\n')
random_line = file.getline(randint(1, lines))

我真的很开心,因为我看到有人可以从我的包裹中受益!很抱歉这个死的答案,但该软件包肯定可以应用于许多其他问题。

答案 4 :(得分:3)

如果您不想阅读整个文件,可以搜索到文件的中间位置,然后向后搜索换行符,然后拨打readline

这是一个Python3脚本,它就是这样做的,

这种方法的一个缺点是短线出现的可能性较低。

def read_random_line(f, chunk_size=16):
    import os
    import random
    with open(f, 'rb') as f_handle:
        f_handle.seek(0, os.SEEK_END)
        size = f_handle.tell()
        i = random.randint(0, size)
        while True:
            i -= chunk_size
            if i < 0:
                chunk_size += i
                i = 0
            f_handle.seek(i, os.SEEK_SET)
            chunk = f_handle.read(chunk_size)
            i_newline = chunk.rfind(b'\n')
            if i_newline != -1:
                i += i_newline + 1
                break
            if i == 0:
                break
        f_handle.seek(i, os.SEEK_SET)
        return f_handle.readline()

答案 5 :(得分:1)

寻找一个随机位置,读一行并丢弃它,然后读另一行。线条的分布不正常,但这并不总是重要的。

答案 6 :(得分:1)

Alex Martelli的answer的稍有改进,该版本处理空文件(通过返回default值):

from random import randrange

def random_line(afile, default=None):
    line = default
    for i, aline in enumerate(afile, start=1):
        if randrange(i) == 0:  # random int [0..i)
            line = aline
    return line

approach可用于使用O(n)时间和O(1)空间从任何迭代器中获取随机项目。

答案 7 :(得分:0)

您可以将这些行添加到set()中,这将随机更改其顺序。

filename=open("lines.txt",'r')
f=set(filename.readlines())
filename.close()

找到第一行:

print(next(iter(f)))

找到第3行:

print(list(f)[2])

列出集合中的所有行:

for line in f:
    print(line)

答案 8 :(得分:0)

这可能很笨重,但我觉得它有效吗? (至少对于txt文件)

import random
choicefile=open("yourfile.txt","r")
linelist=[]
for line in choicefile:
    linelist.append(line)
choice=random.choice(linelist)
print(choice)

它读取文件的每一行,并将其附加到列表中。然后它从列表中选择一个随机行。 如果您想在选择后删除该行,只需执行

linelist.remove(choice)

希望这可能有所帮助,但至少没有额外的模块和导入(除了随机)和相对轻量级。

答案 9 :(得分:0)

import random

with open("file.txt", "r") as f:
    lines = f.readlines()
    print (random.choice(lines))

答案 10 :(得分:0)

如果您不想使用f.read()f.readlines()将整个文件加载到RAM中,则可以通过以下方式获得随机行:

import os
import random


def get_random_line(filepath: str) -> str:
    file_size = os.path.getsize(filepath)
    with open(filepath, 'rb') as f:
        while True:
            pos = random.randint(0, file_size)
            if not pos:  # the first line is chosen
                return f.readline().decode()  # return str
            f.seek(pos)  # seek to random position
            f.readline()  # skip possibly incomplete line
            line = f.readline()  # read next (full) line
            if line:
                return line.decode()  
            # else: line is empty -> EOF -> try another position in next iteration

P.S .:是的,这是Ignacio Vazquez-Abrams在上面的答案中提出的,但是a)他的答案中没有代码,b)我自己想出了这个实现;它可以返回第一行或最后一行。希望对某人有用。

但是,如果您关心分发,那么此代码不是您的选择。

答案 11 :(得分:0)

import random

file = open('file.txt')
full_text = file.readlines()
random_text = random.choice(full_text)
print(random_text)