N linhas aleatórias de Python de um arquivo grande (sem linhas duplicadas)
Eu preciso usar python para pegar o número N de linhas de arquivo txt grande. Esses arquivos são basicamente tabelas delimitadas por tabulações. Minha tarefa tem as seguintes restrições:
Esses arquivos podem conter cabeçalhos (alguns têm cabeçalhos de várias linhas).Os cabeçalhos precisam aparecer na saída na mesma ordem.Cada linha pode ser tomada apenas uma vez.O maior arquivo atualmente é de cerca de 150 GB (cerca de 60.000.000 linhas).As linhas têm aproximadamente o mesmo comprimento em um arquivo, mas podem variar entre arquivos diferentes.Eu usarei normalmente 5000 linhas aleatórias (posso precisar de até 1 000 000 linhas)Atualmente eu escrevi o seguinte código:
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)
Este código parece estar funcionando corretamente.
Estou ciente de que este código prefere linhas que seguem as linhas mais longas na entrada, porque é mais provável que seek () retorne uma posição na linha mais longa e a próxima linha seja gravada na saída. Isso é irrelevante, pois as linhas no arquivo de entrada são aproximadamente do mesmo tamanho. Também estou ciente de que este código resulta em um loop infinito se N for maior que o número de linhas no arquivo de entrada. Não implementarei uma verificação para isso, pois a contagem da linha leva muito tempo.
Limitações de RAM e HDD são irrelevantes. Estou preocupado apenas com a velocidade do programa. Existe uma maneira de otimizar ainda mais esse código? Ou talvez haja uma abordagem melhor?
EDITAR: Para esclarecer, as linhas em um arquivo têm aproximadamente o mesmo tamanho. No entanto, eu tenho vários arquivos que este script precisa ser executado e o comprimento médio de uma linha será diferente para esses arquivos. Por exemplo, o arquivo A pode ter ~ 100 caracteres por linha e arquivo B ~ 50000 caracteres por linha. Eu não sei o comprimento médio da linha de qualquer arquivo de antemão.