Python 哦,谢谢!我将尝试包括这些优化,因为我事先不知道行数。因此,这种方法需要我循环输入文件两次。首先要得到行数。第二步打印所选行。基本上是两次第二次读取所有行,以确定该行是否要输出(在随机数列表中)。我将测试它,因为它不需要很长的时间来写,但我怀疑读取所有行两

Python 哦,谢谢!我将尝试包括这些优化,因为我事先不知道行数。因此,这种方法需要我循环输入文件两次。首先要得到行数。第二步打印所选行。基本上是两次第二次读取所有行,以确定该行是否要输出(在随机数列表中)。我将测试它,因为它不需要很长的时间来写,但我怀疑读取所有行两,python,random,line,large-files,readline,Python,Random,Line,Large Files,Readline,哦,谢谢!我将尝试包括这些优化,因为我事先不知道行数。因此,这种方法需要我循环输入文件两次。首先要得到行数。第二步打印所选行。基本上是两次第二次读取所有行,以确定该行是否要输出(在随机数列表中)。我将测试它,因为它不需要很长的时间来写,但我怀疑读取所有行两次会比N个搜索数(理想情况下)快。也许你可以通过将文件大小除以一行的平均大小(你说你知道)来估计行数,在任何情况下,两次读取文件仍然是O(M).我想我对这条线的长度表达得有点糟糕。我知道一个文件中的行的长度大致相同。但是,文件A和B之间的平均行


哦,谢谢!我将尝试包括这些优化,因为我事先不知道行数。因此,这种方法需要我循环输入文件两次。首先要得到行数。第二步打印所选行。基本上是两次第二次读取所有行,以确定该行是否要输出(在随机数列表中)。我将测试它,因为它不需要很长的时间来写,但我怀疑读取所有行两次会比N个搜索数(理想情况下)快。也许你可以通过将文件大小除以一行的平均大小(你说你知道)来估计行数,在任何情况下,两次读取文件仍然是O(M).我想我对这条线的长度表达得有点糟糕。我知道一个文件中的行的长度大致相同。但是,文件A和B之间的平均行长度可能不同(例如100和50000个字符)。相应地编辑问题。估计行数可能有三个结果。首先,我估计正确,程序按预期运行。其次,估计值太高,这会导致选择一条不存在的线(然后我可以选择一条新的随机线)。第三,估计值太低,最后一行不可能出现在输出中(对此无能为力?)。在任何情况下,我都会尝试这种方法,看看它是如何进行的。因此,您只能阅读第一行并使用它的长度。这并不重要,因为与原始算法中约5000次迭代相比,1次或2次迭代可以忽略不计。你应该试试看它是否运行得更快。类似于zenpoy的建议。我必须查看mmap。读取整个文件需要很多时间。从同一个文件中选择5000行时,单个循环超过60000000行需要比我的算法更多的时间。幸运的是,我可以接受有点偏斜的结果(至少在我当前任务的上下文中)。但如果我需要一个统一的样品,这似乎是一个好办法+我喜欢这个!我有一个类似的问题,我确信我必须读两遍文件。我可能错了,但正如你所描述的,我认为随机选择第一行是不可能的,因为你总是从随机选择的位置向前抓取一大块,并使用下一行。它可以被平衡和微调,以便第一行和最后一行被选中的机会是相同的-这并不难。最好还是将文件放入一个索引的sqlite表中,并使用sql了解文件大小并检索随机行。
inputSize=os.path.getsize(options.input)
usedPositions=[] #Start positions of the lines already in output

with open(options.input) as input:
    with open(options.output, 'w') as output:

        #Handling of header lines
        for i in range(int(options.header)):
            output.write(input.readline())
            usedPositions.append(input.tell())

        # Find and write all random lines, except last
        for j in range(int(args[0])):
            input.seek(random.randrange(inputSize)) # Seek to random position in file (probably middle of line)
            input.readline() # Read the line (probably incomplete). Next input.readline() results in a complete line.
            while input.tell() in usedPositions: # Take a new line if current one is taken
                input.seek(random.randrange(inputSize))
                input.readline() 
            usedPositions.append(input.tell()) # Add line start position to usedPositions
            randomLine=input.readline() # Complete line
            if len(randomLine) == 0: # Take first line if end of the file is reached
                input.seek(0)
                for i in range(int(options.header)): # Exclude headers
                    input.readline()
                randomLine=input.readline()
            output.write(randomLine)            
import random

N = 5000
with open('file.in') as fin:
    line_count = sum(1 for i in fin)
    fin.seek(0)
    to_take = set(random.sample(xrange(line_count), N))
    for lineno, line in enumerate(fin):
        if lineno in to_take:
            pass # use it
#! /usr/bin/python
# coding: utf-8

import random, os


CHUNK_SIZE = 1000
PATH = "/var/log/cron"

def pick_next_random_line(file, offset):
    file.seek(offset)
    chunk = file.read(CHUNK_SIZE)
    lines = chunk.split(os.linesep)
    # Make some provision in case yiou had not read at least one full line here
    line_offset = offset + len(os.linesep) + chunk.find(os.linesep) 
    return line_offset, lines[1]

def get_n_random_lines(path, n=5):
    lenght = os.stat(path).st_size
    results = []
    result_offsets = set()
    with open(path) as input:
        for x in range(n):
            while True:
                offset, line = pick_next_random_line(input, random.randint(0, lenght - CHUNK_SIZE))
                if not offset in result_offsets:
                    result_offsets.add(offset)
                    results.append(line)
                    break
    return results

if __name__ == "__main__":
    print get_n_random_lines(PATH)
import random

def random_sample(n, items):
    results = []

    for i, v in enumerate(items):
        r = random.randint(0, i)
        if r < n:
            if i < n:
                results.insert(r, v) # add first n items in random order
            else:
                results[r] = v # at a decreasing rate, replace random items

    if len(results) < n:
        raise ValueError("Sample larger than population.")

    return results
from itertools import islice

with open(options.input) as input:
    with open(options.output, 'w') as output:

        # Handling of header lines
        # Use islice to avoid buffer issues with .readline()
        for line in islice(input, int(options.header)):
            output.write(line)

        # Pick a random sample
        for line in random_sample(int(args[0]), input):
            output.write(line)