Python组织文件 实践:查找大文件、 用Mb、kb显示文件尺寸 、计算程序运行时间
這個小程序很簡單原本沒有記錄下來的必要,但在編寫過程中又讓我學到了一些新的知識,并且遇到了一些不能解決的問題,然后,然后就很有必要記錄一下。
這個程序的關鍵是獲取文件大小,本來用 os.path.getsize(path) 就能解決,但是我還想讓他用MB、kb這樣的單位來顯示,并且能顯示運行時間,這就又接觸到了新知識,最后在在應用計時模塊timeit時遇到了一個問題,花了很長時間也沒有解決
完整代碼如下:
#! python3 #chapter09-test02.py - 找出一個文件夾內的大文件,并打印出大文件的絕對路徑<br>#-----為了防止運行時間過長,我把程序設置為了只檢查前1000個超過size的文件,他們并不是最大的1000個import os,pprint,sys import timeit,time#裝飾器--計算程序運行時間 def colocked_decorator(func):def colock(*args):startTime=timeit.default_timer()result=func(*args) #運行程序spendTime=timeit.default_timer()-startTimename=func.__name__ #獲取程序名字arg_str=','.join(repr(arg) for arg in args) #注意不是*args 組成程序參數的字符串print('[0.7fs] %s(%s) '%(spendTime,name,arg_str),end='')print('%r',result)return resultreturn colock#尋找指定文件夾內的的大文件 #返回包含所有大文件的絕對地址的一個列表 #folder-指定的文件夾地址 #size-閾值,超過這個為大文件 @colocked_decorator def findBigFile(folder,size):bigFileAbs=[]for foldername,subfolders,filenames in os.walk(folder):#對文件進行遍歷for filename in filenames:#.getsize(path)必須是完整路徑fileAbs=os.path.join(foldername,filename)if os.path.getsize(fileAbs)>size and len(bigFileAbs)<100: #fileAbs=os.path.join(foldername,filename)fileAbs=os.path.abspath(fileAbs)bigFileAbs.append(fileAbs)return bigFileAbs#定義一個函數用來將尺寸變為KB、MB這樣的單位,但是沒有在這個程序中使用 #size-是os.getsize()返回的文件尺寸數值 #is_1024_byte 代表以1024去轉化還是1000去轉化,默認是1024 #先定義的后綴 SUFFIXES = {1000:['KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'],1024:['KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB', 'ZiB', 'YiB']} def humanReadable_size(size,is_1024_byte=True):#mutiple默認是1000mutiple=1000 if is_1024_byte else 1024#與for遍歷結合起來,這樣來進行遞級的轉換for suffix in SUFFIXES[mutiple]:size/=mutiple#直到Size小于能往下一個單位變的數值if size<mutiple:return '{0:.1f}{1}'.format(size,suffix)raise ValueError('number too large')path='F:\DCIM' size=1000000 #設定的閾值 #先判斷路徑是否存在 if os.path.exists(path): resultList=findBigFile(path,size)pprint.pprint(resultList)else:print('You enter path does not exist')sys.exit()轉換大小單位
從網上到的程序是這樣的 來源
但是我看不懂,經過研究,把理解的部分注釋上去了
''' 遇到問題沒人解答?小編創建了一個Python學習交流QQ群:579817333 尋找有志同道合的小伙伴,互幫互助,群里還有不錯的視頻學習教程和PDF電子書! ''' #定義一個函數用來將尺寸變為KB、MB這樣的單位 #size-是os.getsize()返回的文件尺寸數值 #is_1024_byte 代表以1024去轉化還是1000去轉化,默認是1024 #先定義的后綴 SUFFIXES = {1000:['KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'],1024:['KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB', 'ZiB', 'YiB']} def humanReadable_size(size,is_1024_byte=True):#mutiple默認是1000mutiple=1000 if is_1024_byte else 1024#與for遍歷結合起來,這樣來進行遞級的轉換for suffix in SUFFIXES[mutiple]:size/=mutiple#直到Size小于能往下一個單位變的數值if size<mutiple:return '{0:.1f}{1}'.format(size,suffix)raise ValueError('number too large') #拋出異常計算程序運行時間
補充
這是隔了一段時間又看到的一個計時的方法,之前一直用time.time來計時,最近看到了一篇介紹timeit的文章,竟然也很方便,記錄的時候驚訝的發現原來竟然也用過timeit,只是遇到了很多問題,果然好記性不如爛筆頭啊
timeit是python提供的強大的計時庫,不僅使用方便,而且還可以讓函數重復運行
測試語句執行時間:
#看x=1的執行時間,執行1次(number可以省略,默認值為1000000): timeit('x=1', number=1)#看一個列表生成器的執行時間,執行1次: timeit('[i for i in range(10000)]', number=1)測試函數運行時間:
# timeit(函數名_字符串,運行環境_字符串,number=運行次數) t = timeit('func()', 'from __main__ import func', number=1000) print(t)另外一個重復運行repeat
由于電腦永遠都有其他程序也在占用著資源,你的程序不可能最高效的執行。所以一般都會進行多次試驗,取最少的執行時間為真正的執行時間。
''' 遇到問題沒人解答?小編創建了一個Python學習交流QQ群:579817333 尋找有志同道合的小伙伴,互幫互助,群里還有不錯的視頻學習教程和PDF電子書! ''' from timeit import repeatdef func():s = 0for i in range(1000):s += i#repeat和timeit用法相似,多了一個repeat參數,表示重復測試的次數(可以不寫,默認值為3.),返回值為一個時間的列表。 t = repeat('func()', 'from __main__ import func', number=100, repeat=5) print(t) print(min(t))另外,我又學習了計時器的部分信息為程序增加了一個計算查詢耗時的功能
work_time=repeat(findBigFile(path,1000000),'from _main_ import findBigFile',number=1,repeat=1) #repeat=1代表運行一輪,number=1代表每輪運行一次,返回一個每次運行時間的列表但加上之后就出現了錯誤
Traceback (most recent call last):File "C:/Users/Administrator.SC-132/AppData/Local/Programs/Python/Python37/chapter09-test02-判斷文件大小.py", line 45, in <module>'from _main_ import findBigFile',number=1,repeat=1)File "C:\Users\Administrator.SC-201605202132\AppData\Local\Programs\Python\Python37\lib\timeit.py", line 237, in repeatreturn Timer(stmt, setup, timer, globals).repeat(repeat, number)File "C:\Users\Administrator.SC-201605202132\AppData\Local\Programs\Python\Python37\lib\timeit.py", line 128, in __init__raise ValueError("stmt is neither a string nor callable") ValueError: stmt is neither a string nor callable搞了半天無果后發現 stmt是個變量,以為找到了題眼,三秒鐘后發出一聲嘆氣后繼續思考,考慮是否是findBigFile有返回值的原因,遂測試,然而無果
突然發現是語法的問題,要寫成這樣才行。
''' 遇到問題沒人解答?小編創建了一個Python學習交流QQ群:579817333 尋找有志同道合的小伙伴,互幫互助,群里還有不錯的視頻學習教程和PDF電子書! ''' from timeit import timeitdef foo():x=1 work_time=timeit('foo()','from __main__ import foo',number=10)#這里要加引號 print(work_time)這樣可以解決上面的錯誤,能運行了,然后我又測試有參數的函數如下
from timeit import timeitdef foo(argv1,argv2): #這次有參數argv1+=argv2#return argv1num1=1 num2=1 work_time=timeit('foo(num1,num2)','from __main__ import foo',number=10)#這里要加括號 print(work_time)又出現了錯誤
Traceback (most recent call last):File "C:\Users\Administrator.SC-201605202132\AppData\Local\Programs\Python\Python37\forTest.py", line 10, in <module>'from __main__ import foo',number=10)#這里要加括號File "C:\Users\Administrator.SC-201605202132\AppData\Local\Programs\Python\Python37\lib\timeit.py", line 232, in timeitreturn Timer(stmt, setup, timer, globals).timeit(number)File "C:\Users\Administrator.SC-201605202132\AppData\Local\Programs\Python\Python37\lib\timeit.py", line 176, in timeittiming = self.inner(it, self.timer)File "<timeit-src>", line 6, in inner NameError: name 'num1' is not defined我突發奇想把timeit()函數改成了這樣:
work_time=timeit('foo(1,1)','from __main__ import foo',number=10)#直接把值傳進去,不用變量將程序中的代碼改成上面調用方式,經過測試可以運行,只是需要注意假如參數時字符串時,需要注意參數的引號不能與這個函數外部的引號匹配上即:
work_time=timeit('findBigFile("F:\DCIM",1000000)', #這里要使用雙引號'from __main__ import findBigFile',number=1)這樣就好了,然后我想到“沒有定義的變量”這個錯誤是不是由于from __ main__ import foo這里沒有為foo指定參數然后我又這樣試了一下:
work_time=timeit('foo(1,1)','from __main__ import foo(num1,num2)',number=10)然而無效:
Traceback (most recent call last):File "C:\Users\Administrator.SC-201605202132\AppData\Local\Programs\Python\Python37\forTest.py", line 9, in <module>work_time=timeit('foo(1,1)','from __main__ import foo(num1,num2)',number=10)#這里要加括號File "C:\Users\Administrator.SC-201605202132\AppData\Local\Programs\Python\Python37\lib\timeit.py", line 232, in timeitreturn Timer(stmt, setup, timer, globals).timeit(number)File "C:\Users\Administrator.SC-201605202132\AppData\Local\Programs\Python\Python37\lib\timeit.py", line 109, in __init__compile(setup, dummy_src_name, "exec")File "<timeit-src>", line 1from __main__ import foo(num1,num2)^ SyntaxError: invalid syntax我開始去找return Timer(stmt, setup, timer, globals).timeit(number)這里面每個參數的意思,找到了這個:
1) timeit.timeit(stmt='pass', setup='pass', timer=<defaulttimer>, number=1000000)返回:返回執行stmt這段代碼number遍所用的時間,單位為秒,float型 參數:stmt:要執行的那段代碼 setup:執行代碼的準備工作,初始化代碼或構建環境導入語句,不計入時間,一般是import之類的 timer:這個在win32下是time.clock(),linux下是time.time(),默認的,不用管 number:要執行stmt多少遍我覺得這個setup可能有用然后修改代碼:
num4=1 num3=1 work_time=timeit('foo(num1,num2)','num3,num4','from __main__ import foo',number=10)#這里要加括號 print(work_time)出現錯誤
Traceback (most recent call last):File "C:\Users\Administrator.SC-201605202132\AppData\Local\Programs\Python\Python37\forTest.py", line 9, in <module>work_time=timeit('foo(num1,num2)','num3,num4','from __main__ import foo',number=10)#這里要加括號File "C:\Users\Administrator.SC-201605202132\AppData\Local\Programs\Python\Python37\lib\timeit.py", line 232, in timeitreturn Timer(stmt, setup, timer, globals).timeit(number)File "C:\Users\Administrator.SC-201605202132\AppData\Local\Programs\Python\Python37\lib\timeit.py", line 176, in timeittiming = self.inner(it, self.timer)File "<timeit-src>", line 3, in inner NameError: name 'num3' is not defined我有想到是不是可以像from __ main__ import foo一樣去導入變量,
work_time=timeit('foo(num1,num2)','from __main__ import num1','from __main__ import num2','from __main__ import foo',number=10)#這里要加括號又被摩擦了一次
Traceback (most recent call last):File "C:\Users\Administrator.SC-201605202132\AppData\Local\Programs\Python\Python37\forTest.py", line 11, in <module>,'from __main__ import foo',number=10)#這里要加括號 TypeError: timeit() got multiple values for argument 'number'然后放棄,哈哈,感覺一下子解脫了呢
換個思路解決問題,
使用修飾器來為這個帶參數的函數測試時間
''' 遇到問題沒人解答?小編創建了一個Python學習交流QQ群:579817333 尋找有志同道合的小伙伴,互幫互助,群里還有不錯的視頻學習教程和PDF電子書! ''' #裝飾器--計算程序運行時間 def colocked_decorator(func):def colock(*args):startTime=timeit.default_timer()result=func(*args) #運行程序spendTime=timeit.default_timer()-startTimename=func.__name__ #獲取程序名字arg_str=','.join(repr(arg) for arg in args) #注意不是*args 組成程序參數的字符串print('[%0.7fs] %s(%s) '%(spendTime,name,arg_str),end='')print('%r',result)return resultreturn colock遇到的問題:
Traceback (most recent call last):File "C:/Users/Administrator.SC-201605202132/AppData/Local/Programs/Python/Python37/chapter09-test02-判斷文件大小.py", line 59, in <module>resultList=findBigFile(path,size) TypeError: 'NoneType' object is not callable我首先去測試函數不修飾時有沒有問題,經過測試沒有,加上修飾器后才有問題,我就去檢查修飾器,發現了修飾器沒有寫return 修復過后
2) “并非在字符格式化期間轉換所有參數”–字符格式化符號沒寫對
經過檢查是這里的問題
id="__mceDel" print('[0.7fs] %s(%s) '%(spendTime,name,arg_str),end='') 應該為 print('[%0.7fs] %s(%s) '%(spendTime,name,arg_str),end='')總結
以上是生活随笔為你收集整理的Python组织文件 实践:查找大文件、 用Mb、kb显示文件尺寸 、计算程序运行时间的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: python 错误、调试、单元测试、文档
- 下一篇: Python的序列化与反序列化