Python组织文件 实践:查找大文件、 用Mb、kb显示文件尺寸 、计算程序运行时间

这个小程序很简单原本没有记录下来的必要,但在编写过程中又让我学到了一些新的知识,并且遇到了一些不能解决的问题,然后,然后就很有必要记录一下。

这个程序的关键是获取文件大小,本来用 os.path.getsize(path) 就能解决,但是我还想让他用MB、kb这样的单位来显示,并且能显示运行时间,这就又接触到了新知识,最后在在应用计时模块timeit时遇到了一个问题,花了很长时间也没有解决

完整代码如下:

#! python3
#chapter09-test02.py - 找出一个文件夹内的大文件,并打印出大文件的绝对路径
#-----为了防止运行时间过长,我把程序设置为了只检查前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()-startTime name=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 result return 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默认是1000 mutiple=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()

  

转换大小单位  

  从网上到的程序是这样的 来源

  但是我看不懂,经过研究,把理解的部分注释上去了

#定义一个函数用来将尺寸变为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默认是1000
    mutiple=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')  #抛出异常

  计算程序运行时间  

另外,我又学习了计时器的部分信息为程序增加了一个计算查询耗时的功能

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 repeat
    return 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有返回值的原因,遂测试,然而无果

  

  突然发现是语法的问题,要写成这样才行。

from timeit import timeit

def foo():
    x=1
work_time=timeit('foo()','from __main__ import foo',number=10)#这里要加引号
print(work_time)

  这样可以解决上面的错误,能运行了,然后我又测试有参数的函数如下

  

from timeit import timeit

def foo(argv1,argv2):    #这次有参数
    argv1+=argv2
    #return argv1

num1=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 timeit
    return Timer(stmt, setup, timer, globals).timeit(number)
  File "C:\Users\Administrator.SC-201605202132\AppData\Local\Programs\Python\Python37\lib\timeit.py", line 176, in timeit
    timing = 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 timeit
    return 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 1
    from __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 timeit
    return Timer(stmt, setup, timer, globals).timeit(number)
  File "C:\Users\Administrator.SC-201605202132\AppData\Local\Programs\Python\Python37\lib\timeit.py", line 176, in timeit
    timing = 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'

  然后放弃,哈哈,感觉一下子解脱了呢

  换个思路解决问题

使用修饰器来为这个带参数的函数测试时间

#装饰器--计算程序运行时间
def colocked_decorator(func):
    def colock(*args):
        startTime=timeit.default_timer()
        result=func(*args)  #运行程序
        spendTime=timeit.default_timer()-startTime
        name=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 result
    return colock

  

遇到的问题:

  1)

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) “并非在字符格式化期间转换所有参数”--字符格式化符号没写对

Traceback (most recent call last):
  File "C:/Users/Administrator.SC-201605202132/AppData/Local/Programs/Python/Python37/chapter09-test02-判断文件大小.py", line 61, in <module>
    resultList=findBigFile(path,size)
  File "C:/Users/Administrator.SC-201605202132/AppData/Local/Programs/Python/Python37/chapter09-test02-判断文件大小.py", line 16, in colock
    print('[0.7fs] %s(%s) '%(spendTime,name,arg_str),end='')
TypeError: not all arguments converted during string formatting

  经过检查是这里的问题

print('[0.7fs] %s(%s) '%(spendTime,name,arg_str),end='')
应该为
print('[%0.7fs] %s(%s) '%(spendTime,name,arg_str),end='')

  好了

猜你喜欢

转载自www.cnblogs.com/Gaoqiking/p/10475896.html