如何获取Python程序的执行时间?

我有一个Python中的命令行程序需要一段时间才能完成。我想知道完成运行所需的确切时间。

我已经查看了timeit模块,但似乎它只适用于一小部分代码。我想为整个程序计时。

2212916 次浏览

在Linux或Unix中:

$ time python yourprogram.py

在Windows中,请参阅此StackOverflow问题:如何在Windows命令行上测量命令的执行时间?

对于更详细的输出,

$ time -v python yourprogram.pyCommand being timed: "python3 yourprogram.py"User time (seconds): 0.08System time (seconds): 0.02Percent of CPU this job got: 98%Elapsed (wall clock) time (h:mm:ss or m:ss): 0:00.10Average shared text size (kbytes): 0Average unshared data size (kbytes): 0Average stack size (kbytes): 0Average total size (kbytes): 0Maximum resident set size (kbytes): 9480Average resident set size (kbytes): 0Major (requiring I/O) page faults: 0Minor (reclaiming a frame) page faults: 1114Voluntary context switches: 0Involuntary context switches: 22Swaps: 0File system inputs: 0File system outputs: 0Socket messages sent: 0Socket messages received: 0Signals delivered: 0Page size (bytes): 4096Exit status: 0

Python中最简单的方法:

import timestart_time = time.time()main()print("--- %s seconds ---" % (time.time() - start_time))

这假设您的程序至少需要十分之一秒才能运行。

打印:

--- 0.764891862869 seconds ---
import time
start_time = time.clock()main()print(time.clock() - start_time, "seconds")

time.clock()返回处理器时间,它允许我们仅计算此进程使用的时间(无论如何在Unix上)。留档说“无论如何,这是用于基准测试Python或计时算法的函数”

我将这个timing.py模块放入我自己的site-packages目录中,只需在我的模块顶部插入import timing

import atexitfrom time import clock
def secondsToStr(t):return "%d:%02d:%02d.%03d" % \reduce(lambda ll,b : divmod(ll[0],b) + ll[1:],[(t*1000,),1000,60,60])
line = "="*40def log(s, elapsed=None):print lineprint secondsToStr(clock()), '-', sif elapsed:print "Elapsed time:", elapsedprint lineprint
def endlog():end = clock()elapsed = end-startlog("End Program", secondsToStr(elapsed))
def now():return secondsToStr(clock())
start = clock()atexit.register(endlog)log("Start Program")

如果我想显示程序中的重要阶段,我也可以在程序中调用timing.log。但仅包含import timing将打印开始和结束时间以及总运行时间。(请原谅我模糊的secondsToStr函数,它只是将浮点秒数格式化为hh: mm:ss.sss形式。)

注意:可以找到上述代码的Python 3版本这里这里

我真的很喜欢保罗·麦奎尔的回答,但我使用Python 3。所以对于那些感兴趣的人:这里是他的答案的修改,适用于*nix上的Python 3(我想,在Windows下,应该使用clock()而不是time()):

#python3import atexitfrom time import time, strftime, localtimefrom datetime import timedelta
def secondsToStr(elapsed=None):if elapsed is None:return strftime("%Y-%m-%d %H:%M:%S", localtime())else:return str(timedelta(seconds=elapsed))
def log(s, elapsed=None):line = "="*40print(line)print(secondsToStr(), '-', s)if elapsed:print("Elapsed time:", elapsed)print(line)print()
def endlog():end = time()elapsed = end-startlog("End Program", secondsToStr(elapsed))
start = time()atexit.register(endlog)log("Start Program")

如果你觉得这很有用,你仍然应该投票给他的答案,而不是这个,因为他做了大部分的工作;)。

您可以使用Python分析器cProfile来测量cpu时间,以及每个函数在内部花费了多少时间以及每个函数被调用了多少次。如果您想在不知道从哪里开始的情况下提高脚本的性能,这非常有用。这个答案到另一个Stack Overflow问题非常好。看看留档总是很好的。

以下是一个如何从命令行使用cProfile分析脚本的示例:

$ python -m cProfile euler048.py
1007 function calls in 0.061 CPU seconds
Ordered by: standard namencalls  tottime  percall  cumtime  percall filename:lineno(function)1    0.000    0.000    0.061    0.061 <string>:1(<module>)1000    0.051    0.000    0.051    0.000 euler048.py:2(<lambda>)1    0.005    0.005    0.061    0.061 euler048.py:2(<module>)1    0.000    0.000    0.061    0.061 {execfile}1    0.002    0.002    0.053    0.053 {map}1    0.000    0.000    0.000    0.000 {method 'disable' of '_lsprof.Profiler objects}1    0.000    0.000    0.000    0.000 {range}1    0.003    0.003    0.003    0.003 {sum}

我喜欢datetime模块提供的输出,其中时间增量对象以人类可读的方式根据需要显示天、小时、分钟等。

例如:

from datetime import datetimestart_time = datetime.now()# do your work hereend_time = datetime.now()print('Duration: {}'.format(end_time - start_time))

样本输出例如

Duration: 0:00:08.309267

Duration: 1 day, 1:51:24.269711

正如J. F. Sebastian提到的,这种方法可能会遇到一些当地时间的棘手情况,因此使用它更安全:

import timefrom datetime import timedeltastart_time = time.monotonic()end_time = time.monotonic()print(timedelta(seconds=end_time - start_time))

有一个timeit模块可用于计算Python代码的执行时间。

它有详细的留档和Python留档示例,26.6. timeit-测量小代码片段的执行时间

我也喜欢保罗·麦奎尔的回答,并想出了一个更适合我需求的上下文管理器表单。

import datetime as dtimport timeit
class TimingManager(object):"""Context Manager used with the statement 'with' to time some execution.
Example:
with TimingManager() as t:# Code to time"""
clock = timeit.default_timer
def __enter__(self):""""""self.start = self.clock()self.log('\n=> Start Timing: {}')
return self
def __exit__(self, exc_type, exc_val, exc_tb):""""""self.endlog()
return False
def log(self, s, elapsed=None):"""Log current time and elapsed time if present.:param s: Text to display, use '{}' to format the text withthe current time.:param elapsed: Elapsed time to display. Dafault: None, no display."""print s.format(self._secondsToStr(self.clock()))
if(elapsed is not None):print 'Elapsed time: {}\n'.format(elapsed)
def endlog(self):"""Log time for the end of execution with elapsed time."""self.log('=> End Timing: {}', self.now())
def now(self):"""Return current elapsed time as hh:mm:ss string.:return: String."""return str(dt.timedelta(seconds = self.clock() - self.start))
def _secondsToStr(self, sec):"""Convert timestamp to h:mm:ss string.:param sec: Timestamp."""return str(dt.datetime.fromtimestamp(sec))

我已经查看了timeit模块,但似乎它只适用于一小部分代码。我想为整个程序计时。

$ python -mtimeit -n1 -r1 -t -s "from your_module import main" "main()"

它运行your_module.main()函数一次,并使用time.time()函数作为计时器打印经过的时间。

要在Python中模拟/usr/bin/time,请参阅带有 /usr/bin/time的Python子进程:如何捕获定时信息但忽略所有其他输出?

要测量每个函数的CPU时间(例如,不包括time.sleep()期间的时间),您可以使用profile模块(Python 2上的cProfile):

$ python3 -mprofile your_module.py

如果您想使用与profile模块相同的计时器,您可以在上面传递-ptimeit命令。

如何分析Python脚本?

这是对我有用的保罗·麦奎尔的回答。以防有人在运行那个时遇到麻烦。

import atexitfrom time import clock
def reduce(function, iterable, initializer=None):it = iter(iterable)if initializer is None:value = next(it)else:value = initializerfor element in it:value = function(value, element)return value
def secondsToStr(t):return "%d:%02d:%02d.%03d" % \reduce(lambda ll,b : divmod(ll[0],b) + ll[1:],[(t*1000,),1000,60,60])
line = "="*40def log(s, elapsed=None):print (line)print (secondsToStr(clock()), '-', s)if elapsed:print ("Elapsed time:", elapsed)print (line)
def endlog():end = clock()elapsed = end-startlog("End Program", secondsToStr(elapsed))
def now():return secondsToStr(clock())
def main():start = clock()atexit.register(endlog)log("Start Program")

导入文件后从您的程序调用timing.main()

IPython中,“timeit”任何脚本:

def foo():%run bar.pytimeit foo()
from time import timestart_time = time()...end_time = time()time_taken = end_time - start_time # time_taken is in secondshours, rest = divmod(time_taken,3600)minutes, seconds = divmod(rest, 60)

time.clock()

自3.3版以来已弃用:此函数的行为取决于在平台上:使用perf_counter()process_time()代替,根据您的要求,有一个定义良好的行为。

time.perf_counter()

返回性能计数器的值(小数秒),即具有最高可用分辨率的时钟来测量短路持续时间。它是否包括睡眠期间经过的时间,并且是全系统

time.process_time()

返回系统和系统的总和的值(以小数秒为单位)当前进程的用户CPU时间。它不会包括经过的时间睡觉的时候

start = time.process_time()... do somethingelapsed = (time.process_time() - start)

以下代码片段以人类可读的<HH:MM:SS>格式打印经过的时间。

import timefrom datetime import timedelta
start_time = time.time()
## Perform lots of computations.#
elapsed_time_secs = time.time() - start_time
msg = "Execution took: %s secs (Wall clock time)" % timedelta(seconds=round(elapsed_time_secs))
print(msg)

要在Python 2.7中使用metakermit的更新答案,您需要单调包。

代码如下:

from datetime import timedeltafrom monotonic import monotonic
start_time = monotonic()end_time = monotonic()print(timedelta(seconds=end_time - start_time))

Python程序执行度量的时间可能不一致,具体取决于:

  • 相同的程序可以使用不同的算法进行评估
  • 运行时间因算法而异
  • 运行时间因实现而异
  • 运行时间因计算机而异
  • 运行时间无法根据小输入进行预测

这是因为最有效的方法是使用“增长顺序”并学习大“O”符号来正确地完成它。

无论如何,您可以尝试使用以下简单算法评估任何Python程序在特定机器每秒计数步骤中的性能:将其调整到您要评估的程序

import time
now = time.time()future = now + 10step = 4 # Why 4 steps? Because until here already four operations executedwhile time.time() < future:step += 3 # Why 3 again? Because a while loop executes one comparison and one plus equal statementstep += 4 # Why 3 more? Because one comparison starting while when time is over plus the final assignment of step + 1 and print statementprint(str(int(step / 10)) + " steps per second")

只需使用timeit模块。它适用于Python 2和Python 3。

import timeit
start = timeit.default_timer()
# All the program statementsstop = timeit.default_timer()execution_time = stop - start
print("Program Executed in "+str(execution_time)) # It returns time in seconds

它以秒为单位返回,你可以得到你的执行时间。这很简单,但你应该在开始程序执行的w main函数中写这些。如果你想得到执行时间,即使你得到一个错误,然后把你的参数“Start”带到它那里并计算如下:

def sample_function(start,**kwargs):try:# Your statementsexcept:# except statements run when your statements raise an exceptionstop = timeit.default_timer()execution_time = stop - startprint("Program executed in " + str(execution_time))

Timeit是Python中的一个类,用于计算小块代码的执行时间。

Default_timer是这个类中的一个方法,用于测量挂钟计时,而不是CPU执行时间。因此其他进程执行可能会干扰它。因此它对小块代码很有用。

代码示例如下:

from timeit import default_timer as timer
start= timer()
# Some logic
end = timer()
print("Time taken:", end-start)

使用line_profiler

line_profiler将分析每行代码执行所需的时间。分析器通过Cython在C中实现,以减少分析的开销。

from line_profiler import LineProfilerimport random
def do_stuff(numbers):s = sum(numbers)l = [numbers[i]/43 for i in range(len(numbers))]m = ['hello'+str(numbers[i]) for i in range(len(numbers))]
numbers = [random.randint(1,100) for i in range(1000)]lp = LineProfiler()lp_wrapper = lp(do_stuff)lp_wrapper(numbers)lp.print_stats()

结果将是:

Timer unit: 1e-06 s
Total time: 0.000649 sFile: <ipython-input-2-2e060b054fea>Function: do_stuff at line 4
Line #      Hits         Time  Per Hit   % Time  Line Contents==============================================================4                                           def do_stuff(numbers):5         1           10     10.0      1.5      s = sum(numbers)6         1          186    186.0     28.7      l = [numbers[i]/43 for i in range(len(numbers))]7         1          453    453.0     69.8      m = ['hello'+str(numbers[i]) for i in range(len(numbers))]

对于使用jupyter笔记本的数据人员

在单元格中,您可以使用Jupyter的%%time魔术命令来测量执行时间:

%%time[ x**2 for x in range(10000)]

产出

CPU times: user 4.54 ms, sys: 0 ns, total: 4.54 msWall time: 4.12 ms

这只会捕获特定单元格的执行时间。如果您想捕获整个笔记本(即程序)的执行时间,您可以在同一目录中创建一个新笔记本,并在新笔记本中执行所有单元格:

假设上面的笔记本名为example_notebook.ipynb。在同一目录下的新笔记本中:

# Convert your notebook to a .py script:!jupyter nbconvert --to script example_notebook.ipynb
# Run the example_notebook with -t flag for time%run -t example_notebook

产出

IPython CPU timings (estimated):User   :       0.00 s.System :       0.00 s.Wall time:       0.00 s.

我使用了一个非常简单的函数来计时代码执行的一部分:

import timedef timing():start_time = time.time()return lambda x: print("[{:.2f}s] {}".format(time.time() - start_time, x))

而要使用它,只需在代码前调用它来测量以检索函数计时,然后在带有注释的代码后调用函数。时间会出现在注释前面。例如:

t = timing()train = pd.read_csv('train.csv',dtype={'id': str,'vendor_id': str,'pickup_datetime': str,'dropoff_datetime': str,'passenger_count': int,'pickup_longitude': np.float64,'pickup_latitude': np.float64,'dropoff_longitude': np.float64,'dropoff_latitude': np.float64,'store_and_fwd_flag': str,'trip_duration': int,},parse_dates = ['pickup_datetime', 'dropoff_datetime'],)t("Loaded {} rows data from 'train'".format(len(train)))

然后输出将如下所示:

[9.35s] Loaded 1458644 rows data from 'train'

如果你想以微秒为单位测量时间,那么你可以使用以下版本,完全基于保罗·麦奎尔Nicojo的答案——这是Python 3代码。我还为它添加了一些颜色:

import atexitfrom time import timefrom datetime import timedelta, datetime

def seconds_to_str(elapsed=None):if elapsed is None:return datetime.now().strftime("%Y-%m-%d %H:%M:%S.%f")else:return str(timedelta(seconds=elapsed))

def log(txt, elapsed=None):colour_cyan = '\033[36m'colour_reset = '\033[0;0;39m'colour_red = '\033[31m'print('\n ' + colour_cyan + '  [TIMING]> [' + seconds_to_str() + '] ----> ' + txt + '\n' + colour_reset)if elapsed:print("\n " + colour_red + " [TIMING]> Elapsed time ==> " + elapsed + "\n" + colour_reset)

def end_log():end = time()elapsed = end-startlog("End Program", seconds_to_str(elapsed))

start = time()atexit.register(end_log)log("Start Program")

log()=>打印定时信息的函数。

txt==>记录的第一个参数,及其标记计时的字符串。

atexit==>Python模块用于注册程序退出时可以调用的函数。

您只需在Python中执行此操作。没有必要让它变得复杂。

import time
start = time.localtime()end = time.localtime()"""Total execution time in minutes$ """print(end.tm_min - start.tm_min)"""Total execution time in seconds$ """print(end.tm_sec - start.tm_sec)

这是获取程序运行时间的最简单方法:

在程序的最后编写以下代码。

import timeprint(time.clock())

我在很多地方都遇到了同样的问题,所以我创建了一个便利包horology。您可以使用pip install horology安装它,然后以优雅的方式进行:

from horology import Timing
with Timing(name='Important calculations: '):prepare()do_your_stuff()finish_sth()

将输出:

Important calculations: 12.43 ms

或者更简单(如果你有一个函数):

from horology import timed
@timeddef main():...

将输出:

main: 7.12 h

它负责单位和舍入。它适用于python 3.6或更高版本。

稍后回答,但我使用内置的#0

import timeitcode_to_test = """a = range(100000)b = []for i in a:b.append(i*2)"""elapsed_time = timeit.timeit(code_to_test, number=500)print(elapsed_time)# 10.159821493085474

  • 将所有代码包装在code_to_test中,包括您可能拥有的任何导入。
  • number参数指定代码应该重复的次数。
  • 演示

与@rogeriopvl的响应类似,我添加了一个轻微的修改,以使用相同的库将长时间运行的作业转换为小时分钟秒。

import timestart_time = time.time()main()seconds = time.time() - start_timeprint('Time Taken:', time.strftime("%H:%M:%S",time.gmtime(seconds)))

样本输出

Time Taken: 00:00:08

首先,以管理员身份打开命令提示符(CMD)安装人道软件包并在那里键入-pip install humanfriendly

代码:

from humanfriendly import format_timespanimport timebegin_time = time.time()# Put your code hereend_time = time.time() - begin_timeprint("Total execution time: ", format_timespan(end_time))

输出:

在此处输入图片描述

我尝试并使用以下脚本找到了时差。

import time
start_time = time.perf_counter()[main code here]print (time.perf_counter() - start_time, "seconds")

对于函数,我建议使用我创建的这个简单的装饰器。

def timeit(method):def timed(*args, **kwargs):ts = time.time()result = method(*args, **kwargs)te = time.time()if 'log_time' in kwargs:name = kwargs.get('log_name', method.__name__.upper())kwargs['log_time'][name] = int((te - ts) * 1000)else:print('%r  %2.22f ms' % (method.__name__, (te - ts) * 1000))return resultreturn timed
@timeitdef foo():do_some_work()
# foo()# 'foo'  0.000953 ms

这个答案创建了一个简单但方便的工具。

import timefrom datetime import timedelta
def start_time_measure(message=None):if message:print(message)return time.monotonic()
def end_time_measure(start_time, print_prefix=None):end_time = time.monotonic()if print_prefix:print(print_prefix + str(timedelta(seconds=end_time - start_time)))return end_time

用法:

total_start_time = start_time_measure()start_time = start_time_measure('Doing something...')# Do somethingend_time_measure(start_time, 'Done in: ')start_time = start_time_measure('Doing something else...')# Do something elseend_time_measure(start_time, 'Done in: ')end_time_measure(total_start_time, 'Total time: ')

输出:

Doing something...Done in: 0:00:01.218000Doing something else...Done in: 0:00:01.313000Total time: 0:00:02.672000

time.clock在Python 3.3中已被弃用,将从Python 3.8中删除:改用time.perf_countertime.process_time

import timestart_time = time.perf_counter ()for x in range(1, 100):print(x)end_time = time.perf_counter ()print(end_time - start_time, "seconds")

我定义了以下Python装饰器:

def profile(fct):def wrapper(*args, **kw):start_time = time.time()ret = fct(*args, **kw)print("{} {} {} return {} in {} seconds".format(args[0].__class__.__name__,args[0].__class__.__module__,fct.__name__,ret,time.time() - start_time))return retreturn wrapper

并将其用于函数或类/方法:

@profiledef main()...

我使用ttictoc的tic和toc。

pip install ttictoc

然后您可以在脚本中使用:

from ttictoc import tic,toctic()
# foo()
print(toc())

默认情况下,Linux或Unix系统(在macOS上测试)在终端上附带time命令,您可以使用它来运行Python脚本并获取realusersys执行运行脚本的时间信息。

然而,默认输出不是很清楚(至少对我来说),默认的time命令甚至不接受任何选项作为参数来格式化输出。这是因为time中的有两个版本-一个内置在bash中,它只提供最小版本,另一个位于/usr/bin/time上。

/usr/bin/time命令接受-al-h-p-o等附加参数。我最喜欢的是-p,它在新行中显示输出,如下所示:

real 2.18user 17.92sys 2.71

当程序中采用用户输入时,我在查找查找所有素数<=一个数字的两种不同方法的运行时间时遇到的问题。

错误的方法

#Sample input for a number 20#Sample output [2, 3, 5, 7, 11, 13, 17, 19]#Total Running time = 0.634 seconds
import time
start_time = time.time()
#Method 1 to find all the prime numbers <= a Number
# Function to check whether a number is prime or not.def prime_no(num):if num<2:return Falseelse:for i in range(2, num//2+1):if num % i == 0:return Falsereturn True
#To print all the values <= ndef Prime_under_num(n):a = [2]if n <2:print("None")elif n==2:print(2)else:"Neglecting all even numbers as even numbers won't be prime in order to reduce the time complexity."for i in range(3, n+1, 2):if prime_no(i):a.append(i)print(a)

"When Method 1 is only used outputs of running time for different inputs"#Total Running time = 2.73761 seconds #n = 100#Total Running time = 3.14781 seconds #n = 1000#Total Running time = 8.69278 seconds #n = 10000#Total Running time = 18.73701 seconds #n = 100000
#Method 2 to find all the prime numbers <= a Number
def Prime_under_num(n):a = [2]if n <2:print("None")elif n==2:print(2)else:for i in range(3, n+1, 2):if n%i ==0:passelse:a.append(i)print(a)
"When Method 2 is only used outputs of running time for different inputs"# Total Running time = 2.75935 seconds #n = 100# Total Running time = 2.86332 seconds #n = 1000# Total Running time = 4.59884 seconds #n = 10000# Total Running time = 8.55057 seconds #n = 100000
if __name__ == "__main__" :n = int(input())Prime_under_num(n)print("Total Running time = {:.5f} seconds".format(time.time() - start_time))

对于上述所有情况获得的不同运行时间都是错误的。对于获取输入的问题,我们必须在获取输入后才开始时间。这里用户键入输入所需的时间也与运行时间一起计算。

正确的方法

我们必须从开头删除start_time=time.time()并将其添加到主块中。

if __name__ == "__main__" :n = int(input())start_time = time.time()Prime_under_num(n)print("Total Running time = {:.3f} seconds".format(time.time() - start_time))

因此,当单独使用时,这两种方法的输出如下:-

# Method 1
# Total Running time = 0.00159 seconds #n = 100# Total Running time = 0.00506 seconds #n = 1000# Total Running time = 0.22987 seconds #n = 10000# Total Running time = 18.55819 seconds #n = 100000
# Method 2
# Total Running time = 0.00011 seconds #n = 100# Total Running time = 0.00118 seconds #n = 1000# Total Running time = 0.00302 seconds #n = 10000# Total Running time = 0.01450 seconds #n = 100000

现在我们可以看到与错误方法相比,总运行时间有显着差异。尽管方法2在两种方法优先方法(错误方法)中的表现优于方法1是错误的。

我认为这是最好和最简单的方法:

from time import monotonic
start_time = monotonic()# somethingprint(f"Run time {monotonic() - start_time} seconds")

或者一个装饰师:

from time import monotonic    
def record_time(function):def wrap(*args, **kwargs):start_time = monotonic()function_return = function(*args, **kwargs)print(f"Run time {monotonic() - start_time} seconds")return function_returnreturn wrap
@record_timedef your_function():# something