Leia as primeiras N linhas de um arquivo em python

150

Temos um grande arquivo de dados brutos que gostaríamos de cortar para um tamanho especificado. Tenho experiência em .net c #, no entanto, gostaria de fazer isso em python para simplificar as coisas e por interesse.

Como eu iria obter as primeiras N linhas de um arquivo de texto em python? O sistema operacional em uso terá algum efeito na implementação?

Russell
fonte
Eu posso dar n como argumento de linha de comando
Nons

Respostas:

240

Python 2

with open("datafile") as myfile:
    head = [next(myfile) for x in xrange(N)]
print head

Python 3

with open("datafile") as myfile:
    head = [next(myfile) for x in range(N)]
print(head)

Aqui está outra maneira (ambos Python 2 e 3)

from itertools import islice
with open("datafile") as myfile:
    head = list(islice(myfile, N))
print head
John La Rooy
fonte
1
Obrigado, isso é realmente muito útil. Qual é a diferença entre os dois? (em termos de desempenho, bibliotecas necessárias, compatibilidade etc)?
Russell
1
Espero que o desempenho seja semelhante, talvez o primeiro seja um pouco mais rápido. Mas o primeiro não funcionará se o arquivo não tiver pelo menos N linhas. É melhor avaliar o desempenho em relação a alguns dados típicos com os quais você o usará.
31430 John La Rooy
1
A instrução with funciona no Python 2.6 e requer uma instrução de importação extra no 2.5. Para a versão 2.4 ou anterior, seria necessário reescrever o código com uma tentativa ... exceto o bloco. Estilisticamente, prefiro a primeira opção, embora, como mencionado, a segunda seja mais robusta para arquivos curtos.
Alasdair
1
islice é provavelmente mais rápido como ele é implementado em C.
Alice Purcell
22
Tenha em mente que, se os arquivos têm menos de N linhas Isto irá aumentar exceção StopIteration que você deve lidar com
Ilian Iliev
19
N = 10
with open("file.txt", "a") as file:  # the a opens it in append mode
    for i in range(N):
        line = next(file).strip()
        print(line)
ghostdog74
fonte
23
Estremeço sempre que vejo, f = open("file")sem exceção, o tratamento para fechar o arquivo. A maneira Pythonic de manipular arquivos é com um gerenciador de contexto, ou seja, usando a instrução with. Isso é abordado no tutorial Python de saída de entrada . "It is good practice to use the with keyword when dealing with file objects. This has the advantage that the file is properly closed after its suite finishes, even if an exception is raised on the way."
Mark Mikofski
1
Por que abrir o arquivo no modo de acréscimo?
AMC
13

Se você deseja ler as primeiras linhas rapidamente e não se importa com o desempenho, pode usar .readlines()qual objeto da lista de devoluções e depois dividir a lista.

Por exemplo, para as 5 primeiras linhas:

with open("pathofmyfileandfileandname") as myfile:
    firstNlines=myfile.readlines()[0:5] #put here the interval you want

Nota: o arquivo inteiro é lido e, portanto, não é o melhor do ponto de vista do desempenho, mas é fácil de usar, rápido de escrever e fácil de lembrar; portanto, se você quiser apenas executar um cálculo único, é muito conveniente

print firstNlines

Uma vantagem em comparação com as outras respostas é a possibilidade de seleccionar facilmente a gama de linhas por exemplo, pular as primeiras 10 linhas [10:30]ou a dura 10 [:-10]ou tendo apenas linhas pares [::2].

GM
fonte
2
A resposta principal é provavelmente muito mais eficiente, mas essa funciona como um encanto para arquivos pequenos.
precisa saber é o seguinte
2
Observe que isso realmente lê o arquivo inteiro em uma lista primeiro (myfile.readlines ()) e depois emenda as 5 primeiras linhas dele.
AbdealiJK
2
Isso deve ser evitado.
Anilbey
1
Não vejo razão para usar isso, não é mais simples que as soluções muito mais eficientes.
AMC
@AMC obrigado pelo feedback, eu o uso no console para explorar os dados quando preciso dar uma olhada rápida nas primeiras linhas, economizando tempo ao escrever o código.
GM
9

O que faço é chamar as N linhas usando pandas. Eu acho que o desempenho não é o melhor, mas por exemplo se N=1000:

import pandas as pd
yourfile = pd.read('path/to/your/file.csv',nrows=1000)
Cro-Magnon
fonte
3
Melhor seria usar a nrowsopção, que pode ser definida como 1000 e o arquivo inteiro não é carregado. pandas.pydata.org/pandas-docs/stable/generated/… Em geral, o pandas possui essa e outras técnicas de economia de memória para arquivos grandes.
philshem
Sim você está certo. Eu apenas corrijo. Desculpe-me pelo erro.
precisa saber é o seguinte
1
Você também pode querer adicionar seppara definir um delimitador de coluna (que não deve ocorrer em um arquivo não-CSV)
philshem
1
@ Cro-Magnon Não consigo encontrar a pandas.read()função na documentação. Você conhece alguma informação sobre o assunto?
AMC
6

Não existe um método específico para ler o número de linhas expostas pelo objeto de arquivo.

Eu acho que a maneira mais fácil seria seguir:

lines =[]
with open(file_name) as f:
    lines.extend(f.readline() for i in xrange(N))
artdanil
fonte
Isso é algo que eu realmente pretendia. Porém, pensei em adicionar cada linha à lista. Obrigado.
Artdanil
4

Com base na resposta votada pelo topo do gnibbler (20 de novembro de 2009 às 0:27): essa classe adiciona os métodos head () e tail () ao arquivo do objeto.

class File(file):
    def head(self, lines_2find=1):
        self.seek(0)                            #Rewind file
        return [self.next() for x in xrange(lines_2find)]

    def tail(self, lines_2find=1):  
        self.seek(0, 2)                         #go to end of file
        bytes_in_file = self.tell()             
        lines_found, total_bytes_scanned = 0, 0
        while (lines_2find+1 > lines_found and
               bytes_in_file > total_bytes_scanned): 
            byte_block = min(1024, bytes_in_file-total_bytes_scanned)
            self.seek(-(byte_block+total_bytes_scanned), 2)
            total_bytes_scanned += byte_block
            lines_found += self.read(1024).count('\n')
        self.seek(-total_bytes_scanned, 2)
        line_list = list(self.readlines())
        return line_list[-lines_2find:]

Uso:

f = File('path/to/file', 'r')
f.head(3)
f.tail(3)
fdb
fonte
4

As duas maneiras mais intuitivas de fazer isso seriam:

  1. Iterar no arquivo linha por linha e linhas breakposteriores N.

  2. Iterar no arquivo linha por linha usando os tempos do next()método N. (Essa é essencialmente apenas uma sintaxe diferente para o que a resposta principal faz.)

Aqui está o código:

# Method 1:
with open("fileName", "r") as f:
    counter = 0
    for line in f:
        print line
        counter += 1
        if counter == N: break

# Method 2:
with open("fileName", "r") as f:
    for i in xrange(N):
        line = f.next()
        print line

A conclusão é que, desde que você não use readlines()ou enumerateinsira o arquivo inteiro na memória, você terá muitas opções.

FatihAkici
fonte
3

maneira mais conveniente por conta própria:

LINE_COUNT = 3
print [s for (i, s) in enumerate(open('test.txt')) if i < LINE_COUNT]

Solução baseada na compreensão da lista A função open () suporta uma interface de iteração. O enumerate () abrange as tuplas open () e return (índice, item), depois verificamos se estamos dentro de um intervalo aceito (se i <LINE_COUNT) e, em seguida, simplesmente imprimimos o resultado.

Aproveite o Python. ;)

Maxim Plaksin
fonte
Parece apenas uma alternativa um pouco mais complexa [next(file) for _ in range(LINE_COUNT)].
AMC
3

Nas primeiras 5 linhas, basta:

N=5
with open("data_file", "r") as file:
    for i in range(N):
       print file.next()
Surya
fonte
2

Se você deseja algo que obviamente (sem procurar informações esotéricas nos manuais) funcione sem importações e tente / exceto e funcione em uma variedade razoável de versões do Python 2.x (2.2 a 2.6):

def headn(file_name, n):
    """Like *x head -N command"""
    result = []
    nlines = 0
    assert n >= 1
    for line in open(file_name):
        result.append(line)
        nlines += 1
        if nlines >= n:
            break
    return result

if __name__ == "__main__":
    import sys
    rval = headn(sys.argv[1], int(sys.argv[2]))
    print rval
    print len(rval)
John Machin
fonte
2

Se você tiver um arquivo muito grande e supondo que deseja que a saída seja uma matriz numpy, o uso de np.genfromtxt congelará o computador. Isso é muito melhor na minha experiência:

def load_big_file(fname,maxrows):
'''only works for well-formed text file of space-separated doubles'''

rows = []  # unknown number of lines, so use list

with open(fname) as f:
    j=0        
    for line in f:
        if j==maxrows:
            break
        else:
            line = [float(s) for s in line.split()]
            rows.append(np.array(line, dtype = np.double))
            j+=1
return np.vstack(rows)  # convert list of vectors to array
cacosomoza
fonte
Se você tem um arquivo muito grande e presume que deseja que a saída seja uma matriz numpy, esse é um conjunto de restrições bastante único, não vejo realmente nenhuma vantagem nisso em relação às alternativas.
AMC
1

A partir do Python 2.6, você pode tirar proveito de funções mais sofisticadas no clase base de E / S. Portanto, a resposta mais bem avaliada acima pode ser reescrita como:

    with open("datafile") as myfile:
       head = myfile.readlines(N)
    print head

(Você não precisa se preocupar com o fato de seu arquivo ter menos de N linhas, pois nenhuma exceção StopIteration é lançada.)

Steve Bading
fonte
25
De acordo com os documentos N, é o número de bytes a serem lidos, não o número de linhas .
Mark Mikofski
4
N é o número de bytes!
qed
5
Uau. Fale sobre nomes ruins. O nome da função menciona, linesmas o argumento se refere bytes.
ArtOfWarfare
0

Isso funcionou para mim

f = open("history_export.csv", "r")
line= 5
for x in range(line):
    a = f.readline()
    print(a)
Sukanta
fonte
Por que não usar um gerenciador de contexto? De qualquer forma, não vejo como isso melhora as muitas respostas existentes.
AMC
0

Isso funciona para Python 2 e 3:

from itertools import islice

with open('/tmp/filename.txt') as inf:
    for line in islice(inf, N, N+M):
        print(line)
sandyp
fonte
Isso é praticamente idêntico à resposta principal de uma década .
AMC
0

fname = input("Enter file name: ")
num_lines = 0

with open(fname, 'r') as f: #lines count
    for line in f:
        num_lines += 1

num_lines_input = int (input("Enter line numbers: "))

if num_lines_input <= num_lines:
    f = open(fname, "r")
    for x in range(num_lines_input):
        a = f.readline()
        print(a)

else:
    f = open(fname, "r")
    for x in range(num_lines_input):
        a = f.readline()
        print(a)
        print("Don't have", num_lines_input, " lines print as much as you can")


print("Total lines in the text",num_lines)
Shakirul
fonte
-1
#!/usr/bin/python

import subprocess

p = subprocess.Popen(["tail", "-n 3", "passlist"], stdout=subprocess.PIPE)

output, err = p.communicate()

print  output

Este método funcionou para mim

Mansur Ali
fonte
Esta não é realmente uma solução Python, no entanto.
AMC
Eu nem entendo o que está escrito em sua resposta. Por favor, adicione alguma explicação.
Alexei Marinichenko 30/06