我的代码的哪些部分运行时间最长、内存最多?我怎样才能找到需要改进的地方? 在开发过程中,我很确定我们大多数人都会想知道这一点,而且通常情况下存在开发空间。在本文中总结了一些方法来监控Python代码的时间和内存使用情况。 本文将介绍4种方法,前3种方法提供时间信息,第4个方法可以获得内存使用情况。time模块time魔法命令lineprofilermemoryprofilertime模块 这是计算代码运行所需时间的最简单、最直接(但需要手动开发)的方法。他的逻辑也很简单:记录代码运行之前和之后的时间,计算时间之间的差异。这可以实现如下: importtime starttimetime。time() result52 endtimetime。time() print(Timetaken{}sec。format(endtimestarttime)) 下面的例子显示了for循环和列表推导式在时间上的差异:importtimeforloopvs。listcomplistcompstarttimetime。time()result〔iforiinrange(0,1000000)〕listcompendtimetime。time()print(Timetakenforlistcomp{}sec。format(listcompendtimelistcompstarttime))result〔〕forloopstarttimetime。time()foriinrange(0,1000000):result。append(i)forloopendtimetime。time()print(Timetakenforforloop{}sec。format(forloopendtimeforloopstarttime))listcomptimelistcompendtimelistcompstarttimeforlooptimeforloopendtimeforloopstarttimeprint(Difference{}。format((forlooptimelistcomptime)listcomptime100)) 我们都知道for会慢一些Timetakenforlistcomp0。05843973159790039secTimetakenforforloop0。06774497032165527secDifference15。922795107582594time魔法命令 魔法命令是IPython内核中内置的方便命令,可以方便地执行特定的任务。一般情况下都实在jupyternotebook种使用。 在单元格的开头添加time,单元格执行完成后,会输出单元格执行所花费的时间。timedefconvertcms(cm,unitm):Functiontoconvertcmtomorfeetifunitm:returncm100returncm30。48convertcms(1000) 结果如下:CPUtimes:user24s,sys:1s,total:25sWalltime:28。1sOut〔8〕:10。0 这里的CPUtimes是CPU处理代码所花费的实际时间,Walltime是事件经过的真实时间,在方法入口和方法出口之间的时间。lineprofiler 前两个方法只提供执行该方法所需的总时间。通过时间分析器我们可以获得函数中每一个代码的运行时间。 这里我们需要使用lineprofiler包。使用pipinstalllineprofiler。importlineprofilerdefconvertcms(cm,unitm):Functiontoconvertcmtomorfeetifunitm:returncm100returncm30。48LoadtheprofilerloadextlineprofilerUsetheprofilersmagictocallthemethodlprunfconvertcmsconvertcms(1000,f) 输出结果如下:Timerunit:1e06sTotaltime:4e06sFile:varfoldersyff7m0c146ddrrmctd4vpkh0000gnTipykernel22452382784489。pyFunction:convertcmsatline1LineHitsTimePerHitTimeLineContents1defconvertcms(cm,unitm):23Functiontoconvertcmtomorfeet4512。02。050。0ifunitm:6returncm100712。02。050。0returncm30。48 可以看到lineprofiler提供了每行代码所花费时间的详细信息。LineContents:运行的代码Hits:行被执行的次数Time:所花费的总时间(即命中次数x每次命中次数)PerHit:一次执行花费的时间,也就是说TimeHitsXPerHitTime:占总时间的比例 可以看到,每一行代码都详细的分析了时间,这对于我们分析时间相当的有帮助。memoryprofiler 与lineprofiler类似,memoryprofiler提供代码的逐行内存使用情况。 要安装它需要使用pipinstallmemoryprofiler。我们这里监视convertcmsf函数的内存使用情况fromconversionsimportconvertcmsfimportmemoryprofilerloadextmemoryprofilermprunfconvertcmsfconvertcmsf(1000,f) convertcmsf函数在单独的文件中定义,然后导入。结果如下:LineMemusageIncrementOccurrencesLineContents163。7MiB63。7MiB1defconvertcmsf(cm,unitm):23Functiontoconvertcmtomorfeet4563。7MiB0。0MiB1ifunitm:6returncm100763。7MiB0。0MiB1returncm30。48 memoryprofiler提供对每行代码内存使用情况的详细了解。 这里的1MiB(MebiByte)几乎等于1MB。1MiB1。0485761MB 但是memoryprofiler也有一些缺点:它通过查询操作系统内存,所以结果可能与python解释器略有不同,如果在会话中多次运行mprun,可能会注意到增量列报告所有代码行为0。0MiB。这是因为魔法命令的限制导致的。 虽然memoryprofiler有一些问题,但是它就使我们能够清楚地了解内存使用情况,对于开发来说是一个非常好用的工具总结 虽然Python并不是一个以执行效率见长的语言,但是在某些特殊情况下这些命令对我们还是非常有帮助的。 作者:Rishikeshavan