Pythonic способ отслеживать номер строки в stdin [duplicate]

Мне нужно получить количество строк большого файла (сотни тысяч строк) в python. Каков наиболее эффективный способ как с точки зрения памяти, так и по времени?

В данный момент я:

def file_len(fname):
    with open(fname) as f:
        for i, l in enumerate(f):
            pass
    return i + 1

можно сделать лучше?

766
задан SilentGhost 10 May 2009 в 11:22
поделиться

31 ответ

Вы не можете получить ничего лучше.

В конце концов, любое решение должно будет прочитать весь файл, выяснить, сколько \n у вас есть, и вернуть этот результат.

У вас есть лучший способ сделать это, не читая весь файл? Не уверен ... Лучшее решение всегда будет связано с I / O-привязкой, лучше всего это сделать, чтобы убедиться, что вы не используете ненужную память, но похоже, что у вас есть это.

253
ответ дан Yuval Adam 19 August 2018 в 17:00
поделиться
print open('file.txt', 'r').read().count("\n") + 1
5
ответ дан Andrés Torres 19 August 2018 в 17:00
поделиться

результатом открытия файла является итератор, который может быть преобразован в последовательность, которая имеет длину:

with open(filename) as f:
   return len(list(f))

, это более кратким, чем ваш явный цикл, и позволяет избежать enumerate.

3
ответ дан Andrew Jaffe 19 August 2018 в 17:00
поделиться
  • 1
    что означает, что в память необходимо будет прочитать 100-мегабайтный файл. – SilentGhost 10 May 2009 в 12:41
  • 2
    да, хорошая точка, хотя я интересуюсь разницей скорости (в отличие от памяти). Вероятно, возможно создать итератор, который сделает это, но я думаю, что это будет эквивалентно вашему решению. – Andrew Jaffe 10 May 2009 в 12:53
  • 3
    это неприятно с точки зрения памяти ... – Yuval Adam 10 May 2009 в 18:18
  • 4
    -1, это не только память, но и необходимость создавать список в памяти. – orip 21 September 2009 в 22:14

Чтобы завершить описанные выше методы, я попробовал вариант с файловым модулем:

import fileinput as fi   
def filecount(fname):
        for line in fi.input(fname):
            pass
        return fi.lineno()

И передал файл строк длиной 60 мил всем указанным выше методам:

mapcount : 6.1331050396
simplecount : 4.588793993
opcount : 4.42918205261
filecount : 43.2780818939
bufcount : 0.170812129974

Для меня немного неожиданно, что fileinput - это то, что плохо и масштабируется намного хуже, чем все другие методы ...

4
ответ дан BandGap 19 August 2018 в 17:00
поделиться

Однострочное решение bash, подобное , этот ответ , используя современную функцию subprocess.check_output:

def line_count(file):
    return int(subprocess.check_output('wc -l {}'.format(file), shell=True).split()[0])
8
ответ дан Community 19 August 2018 в 17:00
поделиться
  • 1
    Этот ответ должен быть проголосован до более высокого места в этой теме для пользователей Linux / Unix. Несмотря на большинство предпочтений в кросс-платформенном решении, это превосходный способ для Linux / Unix. Для файла csv размером 184 миллиона строк я должен отбирать данные, он обеспечивает наилучшее время выполнения. Другие чистые решения python принимают в среднем 100+ секунд, тогда как вызов подпроцесса wc -l занимает ~ 5 секунд. – Shan Dou 27 June 2018 в 16:06
  • 2
    Да, это очень высокопроизводительно! – 1'' 27 June 2018 в 19:55

Я бы использовал метод файлового объекта Python readlines, как показано ниже:

with open(input_file) as foo:
    lines = len(foo.readlines())

Это открывает файл, создает список строк в файле, подсчитывает длину списка, сохраняет это к переменной и снова закрывает файл.

11
ответ дан Daniel Lee 19 August 2018 в 17:00
поделиться
  • 1
    Хотя это один из первых способов, который приходит на ум, он, вероятно, не очень эффективен для памяти, особенно если подсчитывать строки в файлах до 10 ГБ (как и я), что является примечательным недостатком. – Time Sheep 17 April 2014 в 16:36
  • 2
    ... и есть xreadlines () для больших файлов – dmityugov 4 August 2015 в 13:45
  • 3
    @TimeSheep Это проблема для файлов с many (скажем, миллиардами) небольших строк или файлов с чрезвычайно длинными линиями (скажем, гигабайт на строку)? – robert 3 June 2018 в 17:40
  • 4
    Причина, о которой я прошу, заключается в том, что компилятор должен уметь оптимизировать это, не создавая промежуточный список. – robert 3 June 2018 в 17:41
  • 5
    @dmityugov Per Python docs, xreadlines устарел с 2,3, так как он просто возвращает итератор. for line in file является заявленной заменой. См .: docs.python.org/2/library/stdtypes.html#file.xreadlines – Kumba 5 August 2018 в 22:53

Я изменил буферный случай следующим образом:

def CountLines(filename):
    f = open(filename)
    try:
        lines = 1
        buf_size = 1024 * 1024
        read_f = f.read # loop optimization
        buf = read_f(buf_size)

        # Empty file
        if not buf:
            return 0

        while buf:
            lines += buf.count('\n')
            buf = read_f(buf_size)

        return lines
    finally:
        f.close()

Теперь также пустые файлы и последняя строка (без\n) подсчитываются.

3
ответ дан Dummy 19 August 2018 в 17:00
поделиться
  • 1
    Возможно, также объясните (или добавьте комментарий в коде), что вы изменили и зачем;). Можете дать людям гораздо больше внутри вашего кода намного проще (а не «анализировать» код в мозге). – Styxxy 6 November 2012 в 02:50
  • 2
    Оптимизация цикла, я думаю, позволяет Python выполнять поиск локальной переменной в read_f, python.org/doc/essays/list2str – The Red Pea 3 April 2015 в 15:39

Почему бы не прочитать первые 100 и последние 100 строк и оценить среднюю длину линии, а затем разделить общий размер файла на эти числа? Если вам не нужно точное значение, это может сработать.

1
ответ дан Georg Schölly 19 August 2018 в 17:00
поделиться
  • 1
    Мне нужно точное значение, но проблема в том, что в общем случае длина строки может быть довольно различной. Я боюсь, что ваш подход не будет самым эффективным. – SilentGhost 10 May 2009 в 19:50
def count_text_file_lines(path):
    with open(path, 'rt') as file:
        line_count = sum(1 for _line in file)
    return line_count
1
ответ дан jciloa 19 August 2018 в 17:00
поделиться
  • 1
    Не могли бы вы объяснить, что с ним не так, если вы считаете, что это неправильно? Это сработало для меня. Благодаря! – jciloa 20 December 2017 в 18:04
  • 2
    Мне было бы интересно, почему этот ответ был также отменен. Он выполняет итерацию по файлу по строкам и суммирует их. Мне это нравится, это коротко и точно, что с ним не так? – cessor 16 March 2018 в 12:23

Почему бы не работать следующее?

import sys

# input comes from STDIN
file = sys.stdin
data = file.readlines()

# get total number of lines in file
lines = len(data)

print lines

В этом случае функция len использует входные строки как средство определения длины.

0
ответ дан krakatit 19 August 2018 в 17:00
поделиться
  • 1
    Вопрос заключается не в том, как получить счетчик строк, я сам продемонстрировал в самом вопросе, что я делаю: вопрос состоял в том, как это сделать эффективно. В вашем решении весь файл считывается в память, что по крайней мере неэффективно для больших файлов и, самое большее, невозможно для огромных. – SilentGhost 5 December 2010 в 19:28
  • 2
    На самом деле это, скорее всего, очень эффективно, если только это невозможно. :-) – kindall 19 July 2011 в 19:23

Одна строка, возможно довольно быстро:

num_lines = sum(1 for line in open('myfile.txt'))
476
ответ дан Kyle 19 August 2018 в 17:00
поделиться
  • 1
    его схожая с суммой (последовательность из 1) каждой строки считается равной 1. & gt; & gt; & gt; & gt; & gt; [1 для линии в диапазоне (10)] [1, 1, 1, 1, 1, 1, 1, 1, 1, 1] & gt; & gt; & gt; сумма (1 для линии в диапазоне (10)) 10 & gt; & gt; & gt; – James Sapam 13 December 2013 в 07:22
  • 2
    num_lines = sum (1 для строки в open ('myfile.txt'), если line.rstrip ()) для пустых строк фильтра – Honghe.Wu 3 March 2014 в 11:26
  • 3
    как мы открываем файл, будет ли это автоматически закрываться после того, как мы будем перебирать все элементы? Требуется ли «закрыть ()»? Я думаю, мы не можем использовать 'с open ()' в этом кратком заявлении, не так ли? – Mannaggia 18 March 2014 в 17:31
  • 4
    @Mannaggia, вы правы, было бы лучше использовать «с open (filename)», чтобы убедиться, что файл закрывается, когда это сделано, и еще лучше делает это в блоке try-except, где выбрано исключение IOError, если файл не может быть открыт. – BoltzmannBrain 20 May 2015 в 22:58
  • 5
    Еще одно замечание: это ~ 0,04-0,05 секунды медленнее, чем исходная проблема, заданная в 300 тыс. Текстовых файлах строк – andrew 3 December 2015 в 15:05

Как насчет этого?

import fileinput
import sys

counter=0
for line in fileinput.input([sys.argv[1]]):
    counter+=1

fileinput.close()
print counter
1
ответ дан leba-lev 19 August 2018 в 17:00
поделиться

Если вы хотите получить количество строк в Python в Linux, я рекомендую этот метод:

import os
print os.popen("wc -l file_path").readline().split()[0]

file_path может быть как абстрактным, так и относительным путем. Надеюсь, это поможет.

1
ответ дан lerner 19 August 2018 в 17:00
поделиться
def line_count(path):
    count = 0
    with open(path) as lines:
        for count, l in enumerate(lines, start=1):
            pass
    return count
1
ответ дан mdwhatcott 19 August 2018 в 17:00
поделиться

Здесь представлена ​​программа python для использования библиотеки многопроцессорности для распределения подсчета строк по машинам / ядрам. Мой тест улучшает подсчет 20-миллионного файла линии с 26 секунд до 7 секунд, используя 8-ядерный сервер Windows 64. Примечание: не использование карт памяти делает вещи намного медленнее.

import multiprocessing, sys, time, os, mmap
import logging, logging.handlers

def init_logger(pid):
    console_format = 'P{0} %(levelname)s %(message)s'.format(pid)
    logger = logging.getLogger()  # New logger at root level
    logger.setLevel( logging.INFO )
    logger.handlers.append( logging.StreamHandler() )
    logger.handlers[0].setFormatter( logging.Formatter( console_format, '%d/%m/%y %H:%M:%S' ) )

def getFileLineCount( queues, pid, processes, file1 ):
    init_logger(pid)
    logging.info( 'start' )

    physical_file = open(file1, "r")
    #  mmap.mmap(fileno, length[, tagname[, access[, offset]]]

    m1 = mmap.mmap( physical_file.fileno(), 0, access=mmap.ACCESS_READ )

    #work out file size to divide up line counting

    fSize = os.stat(file1).st_size
    chunk = (fSize / processes) + 1

    lines = 0

    #get where I start and stop
    _seedStart = chunk * (pid)
    _seekEnd = chunk * (pid+1)
    seekStart = int(_seedStart)
    seekEnd = int(_seekEnd)

    if seekEnd < int(_seekEnd + 1):
        seekEnd += 1

    if _seedStart < int(seekStart + 1):
        seekStart += 1

    if seekEnd > fSize:
        seekEnd = fSize

    #find where to start
    if pid > 0:
        m1.seek( seekStart )
        #read next line
        l1 = m1.readline()  # need to use readline with memory mapped files
        seekStart = m1.tell()

    #tell previous rank my seek start to make their seek end

    if pid > 0:
        queues[pid-1].put( seekStart )
    if pid < processes-1:
        seekEnd = queues[pid].get()

    m1.seek( seekStart )
    l1 = m1.readline()

    while len(l1) > 0:
        lines += 1
        l1 = m1.readline()
        if m1.tell() > seekEnd or len(l1) == 0:
            break

    logging.info( 'done' )
    # add up the results
    if pid == 0:
        for p in range(1,processes):
            lines += queues[0].get()
        queues[0].put(lines) # the total lines counted
    else:
        queues[0].put(lines)

    m1.close()
    physical_file.close()

if __name__ == '__main__':
    init_logger( 'main' )
    if len(sys.argv) > 1:
        file_name = sys.argv[1]
    else:
        logging.fatal( 'parameters required: file-name [processes]' )
        exit()

    t = time.time()
    processes = multiprocessing.cpu_count()
    if len(sys.argv) > 2:
        processes = int(sys.argv[2])
    queues=[] # a queue for each process
    for pid in range(processes):
        queues.append( multiprocessing.Queue() )
    jobs=[]
    prev_pipe = 0
    for pid in range(processes):
        p = multiprocessing.Process( target = getFileLineCount, args=(queues, pid, processes, file_name,) )
        p.start()
        jobs.append(p)

    jobs[0].join() #wait for counting to finish
    lines = queues[0].get()

    logging.info( 'finished {} Lines:{}'.format( time.time() - t, lines ) )
30
ответ дан namit 19 August 2018 в 17:00
поделиться
  • 1
    Как это работает с файлами, намного большими, чем основная память? например, 20 ГБ файл в системе с 4 ГБ ОЗУ и 2 ядрами – Brian Minton 23 September 2014 в 22:18
  • 2
    Трудно протестировать сейчас, но я предполагаю, что он будет вставлять файл в файл. – Martlark 24 September 2014 в 12:32
  • 3
    Это довольно аккуратный код. Я с удивлением обнаружил, что быстрее использовать несколько процессоров. Я понял, что ИО будет узким местом. В более старых версиях Python строка 21 требует int () как chunk = int ((fSize / процессы)) + 1 – Karl Henselin 30 December 2014 в 20:45

Вы можете выполнить подпроцесс и запустить wc -l filename

import subprocess

def file_len(fname):
    p = subprocess.Popen(['wc', '-l', fname], stdout=subprocess.PIPE, 
                                              stderr=subprocess.PIPE)
    result, err = p.communicate()
    if p.returncode != 0:
        raise IOError(err)
    return int(result.strip().split()[0])
72
ответ дан nosklo 19 August 2018 в 17:00
поделиться
  • 1
    какова будет версия Windows? – SilentGhost 10 May 2009 в 11:30
  • 2
  • 3
    Вы можете обратиться к этому вопросу SO относительно этого. [Д0] stackoverflow.com/questions/247234/… – Ólafur Waage 10 May 2009 в 11:32
  • 4
    Действительно, в моем случае (Mac OS X) это занимает 0.13s против 0.5s для подсчета количества строк для x в файле (...) & quot; производит, против 1.0s, подсчитывая повторные вызовы str.find или mmap.find. (Файл, который я использовал для тестирования, имеет 1,3 миллиона строк.) – bendin 10 May 2009 в 13:06
  • 5
    Не нужно включать оболочку в это. отредактированный ответ и добавленный примерный код; – nosklo 11 May 2009 в 13:23

Как насчет этого

def file_len(fname):
  counts = itertools.count()
  with open(fname) as f: 
    for _ in f: counts.next()
  return counts.next()
2
ответ дан odwl 19 August 2018 в 17:00
поделиться

Как об этом однострочном лайнере:

file_length = len(open('myfile.txt','r').read().split('\n'))

Получает 0,003 секунды, используя этот метод, чтобы время его в файле 3900 строк

def c():
  import time
  s = time.time()
  file_length = len(open('myfile.txt','r').read().split('\n'))
  print time.time() - s
1
ответ дан onetwopunch 19 August 2018 в 17:00
поделиться
def file_len(full_path):
  """ Count number of lines in a file."""
  f = open(full_path)
  nr_of_lines = sum(1 for line in f)
  f.close()
  return nr_of_lines
7
ответ дан pkit 19 August 2018 в 17:00
поделиться

count = max(enumerate(open(filename)))[0]

4
ответ дан pyanon 19 August 2018 в 17:00
поделиться

Мне пришлось опубликовать это по аналогичному вопросу, пока мой рейтинг репутации не подскочил (спасибо тому, кто наткнулся на меня!).

Все эти решения игнорируют один из способов сделать этот запуск значительно быстрее, а именно, используя небуферизованный (необработанный) интерфейс, используя bytearrays и делая собственную буферизацию. (Это применимо только к Python 3. В Python 2 необработанный интерфейс может использоваться или не использоваться по умолчанию, но в Python 3 вы по умолчанию в Unicode.)

Использование модифицированной версии Я считаю, что следующий код быстрее (и немного больше pythonic), чем любое из предлагаемых решений:

def rawcount(filename):
    f = open(filename, 'rb')
    lines = 0
    buf_size = 1024 * 1024
    read_f = f.raw.read

    buf = read_f(buf_size)
    while buf:
        lines += buf.count(b'\n')
        buf = read_f(buf_size)

    return lines

Используя отдельную функцию генератора, это быстрее запускает smidge:

def _make_gen(reader):
    b = reader(1024 * 1024)
    while b:
        yield b
        b = reader(1024*1024)

def rawgencount(filename):
    f = open(filename, 'rb')
    f_gen = _make_gen(f.raw.read)
    return sum( buf.count(b'\n') for buf in f_gen )

Это можно сделать полностью с выражениями генераторов in-line, использующими itertools, но это выглядит довольно странно:

from itertools import (takewhile,repeat)

def rawincount(filename):
    f = open(filename, 'rb')
    bufgen = takewhile(lambda x: x, (f.raw.read(1024*1024) for _ in repeat(None)))
    return sum( buf.count(b'\n') for buf in bufgen )

Вот мои тайминги:

function      average, s  min, s   ratio
rawincount        0.0043  0.0041   1.00
rawgencount       0.0044  0.0042   1.01
rawcount          0.0048  0.0045   1.09
bufcount          0.008   0.0068   1.64
wccount           0.01    0.0097   2.35
itercount         0.014   0.014    3.41
opcount           0.02    0.02     4.83
kylecount         0.021   0.021    5.05
simplecount       0.022   0.022    5.25
mapcount          0.037   0.031    7.46
73
ответ дан Quentin Pradet 19 August 2018 в 17:00
поделиться
  • 1
    Я работаю с файлами 100Gb +, и ваши rawgencounts - единственное возможное решение, которое я видел до сих пор. Благодаря! – soungalo 10 November 2015 в 12:47
  • 2
    wccount в этой таблице для инструмента оболочки подпроцесса wc? – Anentropic 11 November 2015 в 19:05
  • 3
    нашел это в другом комментарии, я думаю, что это тогда gist.github.com/zed/0ac760859e614cd03652 – Anentropic 11 November 2015 в 19:33
  • 4
    Изменил бы оператор return в первом примере на return sum(map(methodcaller("count", b'\n'), f_gen)), импортировав methodcaller из operator, помогая ускорить это до любого (imap из itertools, а если python2)? Я бы также сконфигурировал математику 1024 * 1024 в _make_gen, чтобы сохранить несколько дополнительных циклов. Хотелось бы увидеть сравнение с примером чистого генератора. – Kumba 5 August 2018 в 22:57

Вот что я использую, кажется довольно чистым:

import subprocess

def count_file_lines(file_path):
    """
    Counts the number of lines in a file using wc utility.
    :param file_path: path to file
    :return: int, no of lines
    """
    num = subprocess.check_output(['wc', '-l', file_path])
    num = num.split(' ')
    return int(num[0])

UPDATE: это немного быстрее, чем использование чистого python, но за счет использования памяти. Подпроцесс разветвит новый процесс с тем же объемом памяти, что и родительский процесс, когда он выполнит вашу команду.

4
ответ дан radtek 19 August 2018 в 17:00
поделиться

Я считаю, что файл с отображением памяти будет самым быстрым решением. Я попробовал четыре функции: функцию, отправленную OP (opcount); простая итерация по строкам в файле (simplecount); readline с картографированной памятью (mmap) (mapcount); и решение для считывания буфера, предложенное Николаем Харечко (bufcount).

Я выполнял каждую функцию пять раз и вычислял среднее время выполнения для текстового файла с 1,2 млн. строк.

Windows XP, Python 2.5, 2 ГБ оперативной памяти, процессор AMD 2 ГГц

Вот мои результаты:

mapcount : 0.465599966049
simplecount : 0.756399965286
bufcount : 0.546800041199
opcount : 0.718600034714

Изменить: номера для Python 2.6:

mapcount : 0.471799945831
simplecount : 0.634400033951
bufcount : 0.468800067902
opcount : 0.602999973297

Таким образом, стратегия чтения буфера, по-видимому, является самой быстрой для Windows / Python 2.6

Вот код:

from __future__ import with_statement
import time
import mmap
import random
from collections import defaultdict

def mapcount(filename):
    f = open(filename, "r+")
    buf = mmap.mmap(f.fileno(), 0)
    lines = 0
    readline = buf.readline
    while readline():
        lines += 1
    return lines

def simplecount(filename):
    lines = 0
    for line in open(filename):
        lines += 1
    return lines

def bufcount(filename):
    f = open(filename)                  
    lines = 0
    buf_size = 1024 * 1024
    read_f = f.read # loop optimization

    buf = read_f(buf_size)
    while buf:
        lines += buf.count('\n')
        buf = read_f(buf_size)

    return lines

def opcount(fname):
    with open(fname) as f:
        for i, l in enumerate(f):
            pass
    return i + 1


counts = defaultdict(list)

for i in range(5):
    for func in [mapcount, simplecount, bufcount, opcount]:
        start_time = time.time()
        assert func("big_file.txt") == 1209138
        counts[func].append(time.time() - start_time)

for key, vals in counts.items():
    print key.__name__, ":", sum(vals) / float(len(vals))
178
ответ дан Ryan Ginstrom 19 August 2018 в 17:00
поделиться
  • 1
    Весь файл с отображением памяти не загружается в память. Вы получаете пространство виртуальной памяти, которое ОС по мере необходимости переходит в оперативную память и выходит из нее. Вот как они обрабатываются в Windows: msdn.microsoft.com/en-us/library/ms810613.aspx – Ryan Ginstrom 12 May 2009 в 15:38
  • 2
    Извините, вот более общая ссылка на файлы с отображением памяти: ru.wikipedia.org/wiki/Memory-mapped_file И спасибо за голосование. :) – Ryan Ginstrom 12 May 2009 в 15:45
  • 3
    Несмотря на то, что это просто виртуальная память, именно это ограничивает этот подход, и поэтому он не будет работать для огромных файлов. Я пробовал его с файлом ~ 1.2 Гб с более чем 10 млн. (полученное с помощью wc -l) и только что получил WindowsError: [Ошибка 8] Недостаточно памяти для обработки этой команды. конечно, это краевой случай. – SilentGhost 12 May 2009 в 17:24
  • 4
    +1 для реальных данных синхронизации. Знаем ли мы, что размер буфера 1024 * 1024 является оптимальным, или есть лучший? – Kiv 19 June 2009 в 21:07
  • 5
    Кажется, что wccount() является самым быстрым gist.github.com/0ac760859e614cd03652 – jfs 31 January 2011 в 09:18

Я получил небольшое (4-8%) улучшение с этой версией, которая повторно использует постоянный буфер, поэтому он должен избегать любой из памяти или накладных расходов GC:

lines = 0
buffer = bytearray(2048)
with open(filename) as f:
  while f.readinto(buffer) > 0:
      lines += buffer.count('\n')

Вы можете играть с помощью размер буфера и, возможно, немного улучшится.

7
ответ дан Scott Persinger 19 August 2018 в 17:00
поделиться
  • 1
    Ницца. Для учета файлов, которые не заканчиваются в\n, добавьте 1 вне цикла, если буфер и буфер [-1]! = '\n' – ryuusenshi 14 November 2013 в 20:37
  • 2
    Ошибка: буфер в последнем раунде может быть не чистым. – Jay 29 November 2014 в 06:07

Что касается меня, этот вариант будет самым быстрым:

#!/usr/bin/env python

def main():
    f = open('filename')                  
    lines = 0
    buf_size = 1024 * 1024
    read_f = f.read # loop optimization

    buf = read_f(buf_size)
    while buf:
        lines += buf.count('\n')
        buf = read_f(buf_size)

    print lines

if __name__ == '__main__':
    main()

причинам: буферизация выполняется быстрее, чем чтение по строкам, а string.count также очень быстро

2
ответ дан SilentGhost 19 August 2018 в 17:00
поделиться
  • 1
    Но так ли? По крайней мере, на OSX / python2.5 версия OP все еще на 10% быстрее в соответствии с timeit.py. – dF. 10 May 2009 в 12:47
  • 2
    возможно, я не проверяю это. – Mykola Kharechko 10 May 2009 в 12:54
  • 3
    Что делать, если последняя строка не заканчивается на '\n'? – tzot 11 May 2009 в 14:21
  • 4
    Я не знаю, как вы его протестировали, dF, но на моей машине это ~ 2,5 раза медленнее, чем любой другой вариант. – SilentGhost 11 May 2009 в 17:25
  • 5
    Вы заявляете, что это будет самый быстрый, а затем состояние, в котором вы его не тестировали. Не очень научный а? :) – Ólafur Waage 11 May 2009 в 19:37

Этот код короче и понятнее. Вероятно, это лучший способ:

num_lines = open('yourfile.ext').read().count('\n')
7
ответ дан Texom512 19 August 2018 в 17:00
поделиться

однострочное решение

import os
os.system("wc -l  filename")  

мой фрагмент

os.system ('wc -l * .txt')

0 bar.txt
1000 command.txt
3 test_file.txt
1003 total
6
ответ дан TheExorcist 19 August 2018 в 17:00
поделиться
  • 1
    Хорошая идея, к сожалению, это не работает на Windows. – Kim 20 January 2017 в 21:06
  • 2
    если вы хотите быть серфингом python, попрощайтесь с окнами. Поверьте мне, вы однажды меня отблагодарите. – TheExorcist 22 January 2017 в 11:38
  • 3
    Я просто подумал, что это будет работать только на окнах. Я предпочитаю работать с самим linux / unix, но при написании программного обеспечения IMHO следует учитывать побочные эффекты, которые могла бы иметь программа при работе в разных ОС. Поскольку OP не упомянул о своей платформе, и в случае, если кто-то всплывает на этом решении через google и копирует его (не подозревая об ограничениях, которые может иметь система Windows), я хотел добавить примечание. – Kim 22 January 2017 в 13:42

Другая возможность:

import subprocess

def num_lines_in_file(fpath):
    return int(subprocess.check_output('wc -l %s' % fpath, shell=True).strip().split()[0])
1
ответ дан whitebeard 19 August 2018 в 17:00
поделиться

Это самая быстрая вещь, которую я нашел, используя чистый python. Вы можете использовать любой объем памяти, который вы хотите, установив буфер, хотя 2 ** 16 кажется приятным пятном на моем компьютере.

from functools import partial

buffer=2**16
with open(myfile) as f:
        print sum(x.count('\n') for x in iter(partial(f.read,buffer), ''))

Я нашел ответ здесь Почему строки чтения из stdin намного медленнее в C ++, чем Python? и немного изменили его. Его очень хорошо читать, чтобы понять, как быстро считать строки, хотя wc -l все еще примерно на 75% быстрее, чем что-либо еще.

8
ответ дан Community 19 August 2018 в 17:00
поделиться
0
ответ дан Colonel Panic 31 October 2018 в 03:48
поделиться
Другие вопросы по тегам:

Похожие вопросы: