我需要在python中获取一个大文件(数十万行)的行数。记忆和时间方面最有效的方法是什么?
现在我这样做了:
def file_len(fname):
with open(fname) as f:
for i, l in enumerate(f):
pass
return i + 1
有没有可能做得更好?
您需要精确的行数还是近似值就足够了?
我需要一个准确的。
使用核心卢克。
我会在for循环之前添加i=-1,因为此代码不适用于空文件。
@传说:我打赌皮科在想,得到文件大小(使用seek(0,2)或equiv),除以大约的行长。你可以在开头读几行来猜测平均行长。
enumerate(f, 1)和Ditch the i + 1?
@ianmackinnon适用于空文件,但在for循环之前必须将i初始化为0。
下面还有另一个(更好的)答案。是否要重新考虑移动勾号?
相关:为什么从STDIN到C++的读行要比Python慢得多?.见此处与wc-l.py的比较。
我最初是想找到一种快速的方法来预先分配一个存储为文本的表。但是,在我的例子中,我发现将值附加到列表(允许列表动态增长)比读取文件两次更快。根据您的I/O速度,这可能是需要考虑的问题。
有更好的方法,不会改变太多。将"r"标志添加到open函数中,这样它就不必自动找出要使用的标志。我对它进行了计时,该方法在没有"r"标志的情况下慢了约0.01秒。
您可以考虑使用终端并运行wc-l yourfilename
您需要首先检查文件是否存在。这可以使用os.path.isfile(fname)完成。我假设fname是完整的路径。然后在用open调用之前,将i初始化为-1。否则,如果文件是空的,您将得到一个unboundlocalerror,因为我不会被初始化。
我不知道效率有多高,但len(f.readlines())看起来可读性更强。
@Riitek:那会读取整个文件,导致内存溢出…
我已经用熊猫做了一些测试,而且似乎快得多。len(pd.read_csv(file_name,header=none))。索引
将文件拆分为多个文件,并使用并行程序或Hadoop?
一行,可能很快:
num_lines = sum(1 for line in open('myfile.txt'))
不错,也适用于空文件。
它是如何工作的?
它类似于和(1的序列),每行都计为1。>>>[1 for line in range(10)][1,1,1,1,1,1,1,1,1]>>>sum(1 for line in range(10))10>>>
num_lines=sum(1代表打开的行(‘myfile.txt’)if line.rstrip())代表筛选空行
当我们打开一个文件时,一旦我们遍历了所有元素,它会自动关闭吗?是否需要"close()"?我认为我们不能在这个简短的语句中使用'with open()',对吗?
如果有一个解释解释为什么它起作用的话,那么对于那些抓住这个答案快速解决问题的人来说,这将是非常有益的。
@Mannaggia您是正确的,最好使用"with open(filename)"来确保文件在完成时关闭,并且最好在try-except块中执行此操作,如果无法打开文件,将引发和ioerror异常。
另一件需要注意的事情是:这比原始问题在30万行文本文件上给出的速度慢大约0.04-0.05秒。
@安德鲁,你确定你测试过……科学地?
如果使用枚举,则不需要求和。除非使用列表理解,否则计数将在for循环之后维护。对于num_行,u in enumerate(open("file.txt")):pass
你能解释一下这行1的作用吗?num_lines=sum(open("myfile.txt")中的行为1)……(这里还是初学者)您能解释一下这行代码是如何计算文件中的行数的吗?我不知道"1"是什么,它是用来干什么的?谢谢
@stryker 1 for line in open(..)基本上为每条线路提供了1的列表(但不是因为它是一个生成器)。因此,如果文本文件包含三行,那么[1 for line in open(...)]将是[1, 1, 1]:对于每行,1将添加到数组中。然后将该列表传递给sum(),后者汇总迭代器内的所有值。所以sum([1,2,3])就是6。在前面的例子中,文本有三行,我们得到了一个[1,1,1]的列表。当求和时,得到3,这当然是行数。这似乎是多余的,但它的内存很便宜。
"可能很快"。代码越少并不意味着代码效率越高。
我们用len()代替sum()怎么样,比如len([l for l in open('myfile.txt')])?
你不会比这更好的。
毕竟,任何解决方案都必须读取整个文件,找出您拥有多少,并返回该结果。
在不读取整个文件的情况下,您有更好的方法吗?不确定。。。最好的解决方案将始终是I/O绑定的,您所能做的最好的就是确保不使用不必要的内存,但看起来您已经覆盖了这一点。
准确地说,即使是wc也在读取文件,但在c中,它可能是相当优化的。
据我所知,python文件IO也是通过C完成的。docs.python.org/library/stdtypes.html文件对象
posix_fadvise()可以使用stackoverflow.com/questions/860893/…虽然我没有注意到任何改进gist.github.com/0ac760859e614cd03652
@托马拉克那是条红鲱鱼。虽然python和wc可能发出相同的系统调用,但python有wc没有的操作码调度开销。
您可以通过采样估计行数。它可以快上千倍。参见:documentroot.com/2011/02/…
其他答案似乎表明这个分类答案是错误的,因此应该删除而不是保留为接受。
使用sum()方法的生成器或列表理解方法是否更快?
这个答案显然是错误的。请参阅glglgl的答案:stackoverflow.com/a/9631635/217802
简直不真实。找线就是找新线。您可以并行读取文件块,并搜索换行符,例如,通过让多个进程搜索内存映射文件的区域。
我相信内存映射文件将是最快的解决方案。我尝试了四个函数:op发布的函数(opcount);对文件中的行进行简单迭代(simplecount;使用内存映射文件的readline(mmap)(mapcount;以及mykola kharechko提供的缓冲区读取解决方案(bufcount)。
我运行了五次每个函数,并计算了120万行文本文件的平均运行时间。
Windows XP、python 2.5、2GB RAM、2 GHz AMD处理器
以下是我的结果:
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('
')
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))
这很有趣,因为我看到了不同的数字。文件的实际大小(字节)?
文件大小为53064630字节。
正如我之前所说,bufcount在我的机器上速度非常慢(最多6次)。mapcount确实是最快的,仅次于wc-l解决方案(stackoverflow.com/questions/845058/…)。我看到的唯一缺点是消耗了额外的100MB内存,这取决于您的设置可能是相当合适的。我认为你的回答应该得到支持:)
整个内存映射文件未加载到内存中。您得到一个虚拟内存空间,操作系统根据需要交换内存。以下是在Windows上处理它们的方法:msdn.microsoft.com/en-us/library/ms810613.aspx
抱歉,这里有一个关于内存映射文件的更一般的参考:en.wikipedia.org/wiki/memory-mapped_file,感谢投票。:)
尽管它只是一个虚拟内存,但它正是限制这种方法的原因,因此对于大型文件来说,它将不起作用。我用~1.2 GB的文件尝试过,文件容量超过了1000万。行(通过wc-l获得)并得到一个windowserror:[错误8]没有足够的存储空间来处理此命令。当然,这是一个边缘案例。
+1用于实时数据。我们知道1024*1024的缓冲区大小是最佳的还是更好的?
似乎wccount()是最快的gist.github.com/0ac760859e614cd03652
我有疑问。当使用opcount()中的另一个函数call enumerate()时,opcount()比simpleCount()效率如何?
@rgk,python中的addition操作符相当昂贵:/但是请注意,两者之间的差别很小。
为什么用r+打开地图,不需要写访问!
我不得不把这个贴在一个类似的问题上,直到我的名誉分数跳了一点(多亏了撞我的人!).
所有这些解决方案都忽略了一种使运行速度大大加快的方法,即使用未缓冲(原始)接口、使用bytearray和执行自己的缓冲。(这仅适用于python 3。在python 2中,原始接口在默认情况下可以使用,也可以不使用,但是在python 3中,您将默认为unicode。)
使用修改过的计时工具,我相信下面的代码比提供的任何解决方案都快(而且稍微多一些Python式的代码):
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'
')
buf = read_f(buf_size)
return lines
使用单独的生成器功能,运行速度更快:
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'
') for buf in f_gen )
这完全可以通过使用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'
') 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
我正在处理100GB以上的文件,您的rawgencounts是目前为止我看到的唯一可行的解决方案。谢谢!
该表中的wccount是否用于子流程shell wc工具?
我在另一条评论中找到了这个,我想是gist.github.com/zed/0ac760859e614cd03652
将第一个示例中的RETURN语句更改为return sum(map(methodcaller("count", b'
'), f_gen)),从operator导入methodcaller,是否有助于加快速度(imap,如果是python2)?我还将构造_make_gen中的1024*1024数学,以节省一些额外的周期。希望也能看到与纯生成器示例的比较。
您可以执行一个子进程并运行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])
Windows版本是什么?
gnuwin32.sourceforge.net/packages/coreutils.htm文件包
你可以参考这个问题。stackoverflow.com/questions/247234/…
实际上,在我的例子(mac os x)中,计算"for x in file(…)"生成的行数需要0.13秒,而计算对str.find或mmap.find的重复调用需要0.5秒。(我用来测试的文件有130万行。)
没有必要让壳牌公司参与其中。编辑答案并添加示例代码;
在命令行上(不需要创建另一个shell的开销),这与更清晰、更可移植的纯Python解决方案一样快。另请参见:stackoverflow.com/questions/849058/…
不是跨平台。
你所说的"跨平台"是指它不适用于Windows。
这里有一个python程序,它使用多处理库在机器/内核之间分配行计数。我的测试使用8核Windows64服务器将2000万在线文件的计数从26秒提高到7秒。注意:不使用内存映射会使事情慢得多。
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 ) )
如何处理比主内存大得多的文件?例如,在具有4GB RAM和2核的系统上有一个20GB的文件
现在很难测试,但我想它会把文件调进调出。
这是非常整洁的代码。我很惊讶地发现使用多个处理器更快。我想IO会成为瓶颈。在旧的python版本中,第21行需要int(),如chunk=int((fsize/processes))+1
它是否将所有文件加载到内存中?如果一场大火的大小比电脑上的内存大呢?
文件被映射到虚拟内存中,因此文件的大小和实际内存量通常不是一个限制。
我将使用python的文件对象方法readlines,如下所示:
with open(input_file) as foo:
lines = len(foo.readlines())
这将打开文件,在文件中创建行列表,计算列表的长度,将其保存到变量中,然后再次关闭文件。
虽然这是人们首先想到的方法之一,但它可能没有很好的内存利用率,尤其是在计算高达10GB的文件中的行数时(就像我这样),这是一个值得注意的缺点。
…大文件有xreadlines()。
@Timesheep对于有许多(比如说,数十亿)小行的文件,或者有非常长的行(比如,每行千兆字节)的文件,这是一个问题吗?
我问的原因是,似乎编译器应该能够通过不创建中间列表来优化这一点。
@dmityugov per python docs,xreadlines从2.3开始就被弃用,因为它只返回一个迭代器。for line in file是规定的替代品。参见:docs.python.org/2/library/stdtypes.html file.xreadlines
这是我用的,看起来很干净:
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])
更新:这比使用纯python快了一点,但代价是内存使用。在执行命令时,子进程将使用与父进程相同的内存占用量派生一个新进程。
作为旁注,这在Windows上当然不起作用。
core utils显然为windows stackoverflow.com/questions/247234/&hellip;提供了"wc"。如果代码最终在prod中的Linux中运行,您也可以在Windows框中使用Linux虚拟机。
或者说WSL,如果你只做这样的事情的话,就要对任何虚拟机给予高度的建议。:-)
是的,很有效。我不是一个windows用户,但从googing我学到了wsl=windows subsystem for linux=)
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
这只是解决方案的句法糖分。
你有没有时间数据显示这更快?
使用时间
我在这个版本中得到了一个小的(4-8%)改进,它重新使用了一个常量缓冲区,因此应该避免任何内存或GC开销:
lines = 0
buffer = bytearray(2048)
with open(filename) as f:
while f.readinto(buffer) > 0:
lines += buffer.count('
')
您可以随意使用缓冲区大小,也许会看到一些改进。
很好。若要说明不以结尾的文件,请在循环外添加1 if buffer和buffer[-1]!=‘n’
一个错误:上一轮的缓冲区可能不干净。
如果在缓冲区之间,一部分以结尾,另一部分以n开头,该怎么办?这将丢失其中的一行新行,我将向变量sudgest存储每个块的结尾和开头,但这可能会给脚本增加更多时间。=(
凯尔的回答
num_lines = sum(1 for line in open('my_file.txt'))
可能是最好的选择
num_lines = len(open('my_file.txt').read().splitlines())
以下是两者的性能比较
In [20]: timeit sum(1 for line in open('Charts.ipynb'))
100000 loops, best of 3: 9.79 μs per loop
In [21]: timeit len(open('Charts.ipynb').read().splitlines())
100000 loops, best of 3: 12 μs per loop
类似于此答案的单行bash解决方案,使用现代subprocess.check_output函数:
def line_count(file):
return int(subprocess.check_output('wc -l {}'.format(file), shell=True).split()[0])
对于Linux/Unix用户,这个答案应该在这个线程中被选到更高的位置。尽管在跨平台解决方案中有大多数偏好,但在Linux/Unix上这是一种极好的方式。对于一个1.84亿行的csv文件,我必须从中提取数据,它提供了最佳的运行时间。其他纯python解决方案平均需要100多秒,而wc -l的子进程调用则需要约5秒。
是的,它的性能非常好!
一线解决方案
import os
os.system("wc -l filename")
我的片段
os.system('wc -l *.txt')
< /块引用>< /块引用>
0 bar.txt
1000 command.txt
3 test_file.txt
1003 total
好主意,但不幸的是,这在Windows上不起作用。
如果你想成为Python冲浪者,向Windows说再见。相信我,有一天你会感谢我的。
我只是认为值得注意的是,这只适用于Windows。我更喜欢自己在Linux/Unix堆栈上工作,但是在编写IMHO软件时,应该考虑程序在不同操作系统下运行时可能产生的副作用。由于OP没有提到他的平台,如果有人通过谷歌在这个解决方案上弹出并复制它(不知道Windows系统可能有什么限制),我想添加注释。
这是我用纯Python找到的最快的东西。你可以通过设置缓冲区来使用你想要的任何数量的内存,尽管2*16在我的电脑上似乎是一个最佳选择。
from functools import partial
buffer=2**16
with open(myfile) as f:
print sum(x.count('
') for x in iter(partial(f.read,buffer), ''))
我在这里找到答案,为什么从STDIN中读取线比Python慢得多?稍微调整了一下。了解如何快速计算行数是一个很好的读物,尽管wc -l仍然比其他任何东西快75%。
这段代码简短明了。这可能是最好的方法:
num_lines = open('yourfile.ext').read().count('
')
您还应该关闭该文件。
这个简单的脚本适用于小文件。
它将把整个文件加载到内存中。
为了完成上面的方法,我尝试了一个文件输入模块的变体:
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
让我有点惊讶的是,文件输入如此糟糕,扩展比所有其他方法都糟糕…
简单方法:
num_lines = len(list(open('myfile.txt')))
在此示例中,文件未关闭。
也许是小文件…
OP想要一些记忆效率高的东西。这绝对不是。
print open('file.txt', 'r').read().count("
") + 1
对于我来说,这个变种将是最快的:
#!/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('
')
buf = read_f(buf_size)
print lines
if __name__ == '__main__':
main()
原因:缓存比逐行读取快,string.count也很快
是吗?至少在osx/python2.5上,根据timeit.py的说法,OP的版本仍然快了10%。
也许,我不测试它。
如果最后一行不以''结尾怎么办?
我不知道你是如何测试它的,df,但是在我的机器上,它比任何其他选项慢2.5倍。
您声明它将是最快的,然后声明您没有测试过它。不是很科学吧?:)
请参阅下面的Ryan Ginstrom答案提供的解决方案和统计数据。也可以查看JF塞巴斯蒂安的评论和同一答案的链接。
它显示:mapcount()和wccount()都比buffcount快,尽管buffcount似乎比opcount和simplecount快。
我对缓冲区的修改如下:
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('
')
buf = read_f(buf_size)
return lines
finally:
f.close()
现在还将计算空文件和最后一行(不带)。
也许还可以解释(或在代码中添加注释)您更改了什么以及为什么;)。可能会让人们更容易理解你的代码(而不是"解析"大脑中的代码)。
我认为循环优化允许python在read_f,python.org/doc/随笔/list2str执行局部变量查找。
打开文件的结果是一个迭代器,它可以转换为序列,序列的长度为:
with open(filename) as f:
return len(list(f))
这比显式循环更简洁,并避免使用enumerate。
这意味着需要将100MB文件读取到内存中。
是的,很好,不过我想知道速度(与记忆不同)的不同。可能可以创建一个这样做的迭代器,但我认为它相当于您的解决方案。
就记忆而言,这很糟糕…
-1,它不仅是内存,还必须在内存中构建列表。
count = max(enumerate(open(filename)))[0]
这将给出真值的计数-1。
enumerate()的可选第二个参数是根据docs.python.org/2/library/functions.html enumerate开始计数
这个怎么样?
def file_len(fname):
counts = itertools.count()
with open(fname) as f:
for _ in f: counts.next()
return counts.next()
如果要在Linux中以较低的成本获得python中的行数,我建议使用以下方法:
import os
print os.popen("wc -l file_path").readline().split()[0]
文件路径既可以是抽象文件路径,也可以是相对路径。希望这能有所帮助。
这个怎么样?
import fileinput
import sys
counter=0
for line in fileinput.input([sys.argv[1]]):
counter+=1
fileinput.close()
print counter
这条班轮怎么样:
file_length = len(open('myfile.txt','r').read().split('
'))
使用此方法在3900行文件上花费0.003秒的时间
def c():
import time
s = time.time()
file_length = len(open('myfile.txt','r').read().split('
'))
print time.time() - s
def line_count(path):
count = 0
with open(path) as lines:
for count, l in enumerate(lines, start=1):
pass
return count
您可以按以下方式使用os.path模块:
import os
import subprocess
Number_lines = int( (subprocess.Popen( 'wc -l {0}'.format( Filename ), shell=True, stdout=subprocess.PIPE).stdout).readlines()[0].split()[0] )
,其中Filename是文件的绝对路径。
这个答案与os.path有什么关系?
另一种可能性:
import subprocess
def num_lines_in_file(fpath):
return int(subprocess.check_output('wc -l %s' % fpath, shell=True).strip().split()[0])
不是多平台=/
def count_text_file_lines(path):
with open(path, 'rt') as file:
line_count = sum(1 for _line in file)
return line_count
如果你认为它是错的,你能解释一下它有什么问题吗?这对我很有用。谢谢!
我想知道为什么这个答案也被否决了。它按行对文件进行迭代,并对它们进行汇总。我喜欢它,它很短,而且直截了当,有什么问题吗?
如果文件可以装入内存,则
with open(fname) as f:
count = len(f.read().split(b'
')) - 1
创建名为count.py的可执行脚本文件:
#!/usr/bin/python
import sys
count = 0
for line in sys.stdin:
count+=1
然后将文件的内容通过管道传输到python脚本:cat huge.txt | ./count.py。管道也可以在PowerShell上工作,因此您最终将计算行数。
对我来说,在Linux上,它比:
count=1
with open('huge.txt') as f:
count+=1
如果文件中的所有行的长度相同(并且只包含ASCII字符)*,则可以非常便宜地执行以下操作:
fileSize = os.path.getsize( pathToFile ) # file size in bytes
bytesPerLine = someInteger # don't forget to account for the newline character
numLines = fileSize // bytesPerLine
*我怀疑如果使用像_这样的Unicode字符,需要更多的努力来确定一行中的字节数。
为什么下面的工作不行?
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函数使用输入行作为确定长度的方法。
问题不在于如何计算行数,我已经在问题本身中演示了我在做什么:问题是如何有效地做到这一点。在您的解决方案中,整个文件都被读取到内存中,这对于大型文件来说至少是低效的,对于大型文件来说是不可能的。
实际上,它可能非常有效,除非它是不可能的。-)
这个怎么样?
import sys
sys.stdin=open('fname','r')
data=sys.stdin.readlines()
print"counted",len(data),"lines"
我认为它并没有解决这个大文件正在被读取到内存中的问题。
打印"counted",len(数据),"lines"^语法错误:无效语法
为什么不读取前100行和后100行并估计平均行长度,然后将总文件大小除以这些数字?如果你不需要一个精确的值,这是可行的。
我需要一个精确的值,但问题是一般情况下,行长度可能会有很大的不同。恐怕你的方法不是最有效的。
类似地:
lines = 0
with open(path) as f:
for line in f:
lines += 1