需求:需要統計一個文件的行數
討論:最簡單的辦法是把文件讀入一個大的列表中,然后統計列表的長度.如果文件的路徑是以參數的形式filepath傳遞的,那么只用一行代碼就可以完成我們的需求了。
file_path = r'F:\orm模塊\a.txt'
count = len(open(file_path).readlines())
print(count)
如果是非常大的文件,上面的方法可能很慢,甚至失效.此時,可以使用循環來處理:
file_path = r'F:\orm模塊\a.txt'
count = -1
for count, line in enumerate(open(file_path, 'rU')):
pass
count += 1
print(count)
另外一種處理大文件比較快的方法是統計文件中換行符的個數'\n
'(或者包含'\n'的字串,如在windows系統中):
file_path = r'F:\orm模塊\a.txt'
count = 0
file_obj = open(file_path, 'rb')
while True:
buffer = file_obj.read(8192 * 1024)
if not buffer:
break
count += buffer.count(b'\n')
print(count+1)
file_obj.close()
參數'rb'是必須的,否則在windows系統上,上面的代碼會非常慢.
當 外部系統提供統計行數的方法時,你可以使用它們(通過os.popen),如unix的wc - l.當然,通過自己的程序來完成會更簡單,快捷和通用.你可以假設大多數的文本文件都有合理的大小,所以把它們一次讀入內存中處理是可行的.對於這樣的情 況,len方法返回readlines的大小是最簡單的.
加入一個文件的大小大於內存(比如,有好幾百M那么大),那個最簡單的方法會變得難以忍受的慢,因為操作系統要使用虛擬內存,並不停同過硬盤來換頁.也可能出現失敗的情況 ,就是虛擬內存不夠大.一台有256M內存的機器,當處理一個1G或2G大小的文件的時候,仍然可能出現嚴重的問題.在這種情況下,使用循環處理是比較好的方式,enumerate保存了函數.
第三種方法的核心思想是統計緩存中回車換行字符的個數.這可能最不容易直接想到的方法,也是最不通用的方法,但它可能是最快的方法.
當然,在大多數情況下,性能並不是最重要的,但如果它是的話,影響性能的部分往往不是我們的直覺告訴我們的地方,所以請千萬不要相信自己的直覺, 要考評估和測量來判斷.舉例說明,對於一個中等大小的unix日志文件,比如一個18M的文本,包含了230,000行:
[situ@tioni nuc]$ wc nuc
231581 2312730 18508908 nuc
使用下面的測試文件,bench.py:
import time
from pygments.util import xrange
file_path = r'F:\orm模塊\a.txt'
def timeo(fun, n=10):
start = time.clock( )
for i in xrange(n): fun( )
end_time = time.clock( )
the_time = end_time-start
return (fun.__name__, the_time)
import os
def linecount_w( ):
return int(os.popen('wc -l nuc').read( ).split( )[0])
def linecount_1( ):
return len(open(file_path).readlines( ))
def linecount_2( ):
count = -1
for count, line in enumerate(open(file_path)): pass
return count+1
def linecount_3( ):
count = 0
the_file = open(file_path, 'rb')
while True:
buffer = the_file.read(65536)
if not buffer: break
count += buffer.count(b'\n')
return count
for f in linecount_w, linecount_1, linecount_2, linecount_3:
print(f.__name__, f( ))
for f in linecount_1, linecount_2, linecount_3:
print ("%s: %.2f"%timeo(f))
首先我調用所有的方法來讀文件,以確保不會發生異常情況(如果發生的話程序會中止),接下來,在函數timo中,我調用每種方法10次,然后看看結果,這是一個比較舊但比較穩定的機器:
[situ@tioni nuc]$ python -O bench.py
linecount_w 231581
linecount_1 231581
linecount_2 231581
linecount_3 231581
linecount_1: 4.84
linecount_2: 4.54
linecount_3: 5.02
可以看出,性能上的差別不是很大,實際上,一般用戶不會在意10%左 右的性能差別.另外,最快的方法是用循環處理文件對象,而最慢的方法是統計換行符的個數.在實際中,假如不考慮處理那些好幾百M的大文件,我總是會選中第一種最簡單的方法.
測量代碼的性能是很重要的,Python標准庫也提供了timeit來實現這些工作.我建議你使用timeit,而不是像我在本節做的那樣,自己寫測試代碼,我寫的代碼是好幾年前的事情了,現在既然有了timeit,就沒有必要再使用它了.
統計壓縮文件行數
import zipfile, os
file_path = r'F:\orm模塊\day65.zip'
z = zipfile.ZipFile(file_path, "r")
# 打印zip文件中的文件列表
total_line = 0
code_line = 0
comment_line = 0
file_size = 0
for filename in z.namelist():
content = z.read(filename)
if not len(content): continue
file_size += len(content) # 文件大小統計
with open('tmp', 'wb') as f1:
f1.write(content)
with open('tmp', 'rb') as f2:
for line in f2:
total_line += 1 # 文件行數統計
if not line.strip(): continue
if line.strip().startswith(b'#'):
comment_line += 1 # 注釋行統計
else:
code_line += 1 # 代碼行統計
os.remove('tmp')
print(total_line)
print(code_line)
print(comment_line)
print(file_size)
來自:http://blog.sina.com.cn/s/blog_48acdd250100qh93.html