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


975

我在Python中有一个命令行程序,需要花一些时间才能完成。我想知道完成跑步所需的确切时间。

我看过该timeit模块,但似乎仅适用于少量代码段。我想安排整个节目的时间。

Answers:


1719

Python中最简单的方法:

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

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

印刷品:

--- 0.764891862869 seconds ---

58
尽管这会计算实时时间(包括其他程序使用的时间),所以当您的计算机忙于执行其他工作时,它似乎会花费更多时间
newacct

35
在Windows上,执行相同的操作,但是使用time.clock()而不是time.time()。您将获得更好的准确性。
科里·戈德堡

33
我建议这样做round(time.time() - start_time, 2)(或您想要的任何小数),我会得到像1.24e-5这样的科学数字。
ThorSummoner 2015年

16
@ThorSummoner:您可能想要'%.2f'代替round()这里。
jfs 2015年

10
这种方法有一个很大的缺陷。如果程序运行时系统时间发生了变化(例如与时间服务器同步),则此方法将无法工作,甚至可能会破坏代码(负持续时间...)
Gilad

210

我将此timing.py模块放入自己的site-packages目录中,然后将其插入import timing模块顶部:

import atexit
from 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 = "="*40
def log(s, elapsed=None):
    print line
    print secondsToStr(clock()), '-', s
    if elapsed:
        print "Elapsed time:", elapsed
    print line
    print

def endlog():
    end = clock()
    elapsed = end-start
    log("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版本可以在此处此处找到。


8
如果您按Ctrl-C来停止程序,这是一个真正的干净解决方案。
索林2010年

很好的解决方案,我肯定会使用它并创建一个定时装饰器来识别瓶颈功能
c24b 2014年

9
对于Python 3 from functools import reduce,在顶部添加 并在每个print语句周围放置方括号。很棒!
PowerApp101 2015年

2
@ PowerApp101-谢谢-Nicojo的答案提供了此模块的Py3友好版本。
PaulMcG 2015年

4
注意:time.clock()自版本3.3起已不推荐使用:此功能的行为取决于平台:根据需要,使用perf_counter()[不带时间睡眠]或process_time()[不带时间睡眠],具体取决于您的要求。具有明确的行为。”
2015年

174

在Linux或Unix中:

$ time python yourprogram.py

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

要获得更详细的输出,

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

因此,如果我要启动另一个小部件(例如QT应用程序中的示例),我们如何计算该小部件显示所需的时间?
Ciasto piekarz

1
对于小部件情况,如果要从Python程序启动,请使用rogeriopvl接受的答案。
steveha 2013年

但这似乎并没有在min:seconds中给出时间,而是以浮点数结尾!
Ciasto piekarz

3
是的,它给出了几秒钟。您可以根据需要将其转换为min:seconds。看一下Paul McGuire的答案及其secondsToStr()功能。
steveha

68

我真的很喜欢Paul McGuire的答案,但是我使用Python3。因此,对于那些感兴趣的人:这是他的答案的一种修改,可用于* nix上的Python 3(我想在Windows下,clock()应该使用代替time()):

#python3
import atexit
from time import time, strftime, localtime
from 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 = "="*40
    print(line)
    print(secondsToStr(), '-', s)
    if elapsed:
        print("Elapsed time:", elapsed)
    print(line)
    print()

def endlog():
    end = time()
    elapsed = end-start
    log("End Program", secondsToStr(elapsed))

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

如果您认为此方法有用,则仍应投票赞成他的答案,而不是像他所做的大部分工作一样;)。


1
我发现timedelta(seconds=t).total_seconds()有帮助。
nu Everest,2015年

您能解释一下这些功能的作用吗?log命令中的s是什么?什么是atexit?
SumNeuron '16

简而言之,@ SumNeuron这些功能可以打印出您使用它的程序的执行时间。s是log的第一个参数,应为字符串。日志是一项输出定时信息的功能。atexit是一个python模块,可让您注册要在程序出口处调用的函数。
Nicojo

@Nicojo非常有帮助。我对如何使用此代码测试例如循环执行时间有疑问。假设我有一个导致循环的函数,并且我想获得此循环所花费的时间
moudi

@moudi这个问题的最佳答案是最好的选择。只需在循环之前设置开始时间,然后计算循环结束时的经过时间即可。
Nicojo

67
import time

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

time.clock()返回处理器时间,这使我们只能计算该进程使用的时间(无论如何在Unix上)。该文档说“无论如何,这是用于基准化Python或计时算法的功能”


14
time.time()最好在* nix上使用。time.clock()最好在Windows上使用。
科里·戈德堡

我相信这不能用于计算“仅此过程所用的时间”,因为它使用系统时间并且会受到其他系统过程的影响吗?如果我错了
指正

6
注意:time.clock()自版本3.3起已不推荐使用:此功能的行为取决于平台:根据需要,使用perf_counter()[不带时间睡眠]或process_time()[不带时间睡眠],具体取决于您的要求。具有明确的行为。”
2015年

55

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

例如:

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

样品输出,例如

Duration: 0:00:08.309267

要么

Duration: 1 day, 1:51:24.269711

正如JF Sebastian提到的那样,这种方法在本地时间可能会遇到一些棘手的情况,因此使用起来更安全:

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

1
@phansen:您可以timedelta(seconds=time.monotonic()-start)在这里使用(或者time.time()如果间隔很大)。不要减去代表本地时间的朴素的datetime对象;本地时间不单调
JFS

好的,您的意思是start_time = time.monotonic(); end_time = time.monotonic(); timedelta(seconds=end_time - start_time)。我相信您是对的,但是回来时还必须对其进行格式化datetime.timedelta(0, 0, 76)。此外,似乎在Python 3只添加了单调方法
metakermit

喔好吧。我看到您可以将其传递str()为“人类”。我将更新答案,谢谢。
metakermit

53

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

这是一个示例,如何从命令行使用cProfile来分析脚本:

$ python -m cProfile euler048.py

1007 function calls in 0.061 CPU seconds

Ordered by: standard name
ncalls  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}

@jacwah您如何总计时间?
Chuck

@Chuck第一行说X function calls in Y CPU seconds。如果要使用挂钟时间,请在此处使用其他答案之一。
jacwah

28

对于Linux甚至更好: time

$ time -v python rhtest2.py

    Command being timed: "python rhtest2.py"
    User time (seconds): 4.13
    System time (seconds): 0.07
    Percent of CPU this job got: 91%
    Elapsed (wall clock) time (h:mm:ss or m:ss): 0:04.58
    Average shared text size (kbytes): 0
    Average unshared data size (kbytes): 0
    Average stack size (kbytes): 0
    Average total size (kbytes): 0
    Maximum resident set size (kbytes): 0
    Average resident set size (kbytes): 0
    Major (requiring I/O) page faults: 15
    Minor (reclaiming a frame) page faults: 5095
    Voluntary context switches: 27
    Involuntary context switches: 279
    Swaps: 0
    File system inputs: 0
    File system outputs: 0
    Socket messages sent: 0
    Socket messages received: 0
    Signals delivered: 0
    Page size (bytes): 4096
    Exit status: 0

18

time.clock()

从版本3.3开始不推荐使用:此功能的行为取决于平台:根据您的要求,使用perf_counter()process_time()来具有明确定义的行为。

time.perf_counter()

返回性能计数器的值(以小数秒为单位),即具有最高可用分辨率的时钟以测量较短的持续时间。它的确包含整个系统的睡眠时间。

time.process_time()

返回当前进程的系统和用户CPU时间之和的值(以秒为单位)。它包括睡眠期间经过的时间。

start = time.process_time()
... do something
elapsed = (time.process_time() - start)

1
也许从结论“ Use time.process_time()”开始(或类似)?
彼得·莫滕森

17

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

import timeit

start = timeit.default_timer()

# All the program statements
stop = timeit.default_timer()
execution_time = stop - start

print("Program Executed in "+str(execution_time)) # It returns time in seconds

它以秒为单位返回,您可以拥有执行时间。很简单,但是您应该将它们写在开始程序执行的主函数中。如果即使在遇到错误时也想获得执行时间,则将参数“开始”添加到该位置并进行计算,例如:

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

难道不是那finally一部分吗?
alper

12

以下代码段以一种易于阅读的<HH:MM:SS>格式打印经过的时间。

import time
from 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)    

1
一直到这里,人们找到了最合理的答案(“合理”的意思是尽可能多地依赖内置函数,因此打字最少)。
ijoseph '17

8
from time import time
start_time = time()
...
end_time = time()
time_taken = end_time - start_time # time_taken is in seconds
hours, rest = divmod(time_taken,3600)
minutes, seconds = divmod(rest, 60)


8

我已经看过timeit模块,但似乎只适用于小段代码。我想安排整个节目的时间。

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

它运行一次your_module.main()功能,并使用以下命令打印经过的时间time.time()功能作为计时器。

/usr/bin/time在Python中进行仿真,请参见带有/ usr / bin / time的Python子进程:如何捕获计时信息,但忽略所有其他输出?

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

$ python3 -mprofile your_module.py

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

请参阅如何配置Python脚本?


7

我也喜欢Paul McGuire的答案,并提出了一个更适合我需求的上下文管理器表格。

import datetime as dt
import 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 with
            the 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))

7

对于使用Jupyter Notebook的数据人员

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

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

输出量

CPU times: user 4.54 ms, sys: 0 ns, total: 4.54 ms
Wall 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.


5

使用line_profiler

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

from line_profiler import LineProfiler
import 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 s
File: <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))]

5

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

import time
def 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'

5

我在很多地方都遇到过同样的问题,所以我创建了一个便利包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

@timed
def main():
    ...

将输出:

main: 7.12 h

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


@DarrenZou 在此处
hans

我可以在变量中获取这些值吗?
PepeElMago33

是的,请使用main.interval
汉斯

3

这是Paul McGuire的答案,对我有用。以防万一有人在运行那个困难。

import atexit
from time import clock

def reduce(function, iterable, initializer=None):
    it = iter(iterable)
    if initializer is None:
        value = next(it)
    else:
        value = initializer
    for 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 = "="*40
def log(s, elapsed=None):
    print (line)
    print (secondsToStr(clock()), '-', s)
    if elapsed:
        print ("Elapsed time:", elapsed)
    print (line)

def endlog():
    end = clock()
    elapsed = end-start
    log("End Program", secondsToStr(elapsed))

def now():
    return secondsToStr(clock())

def main():
    start = clock()
    atexit.register(endlog)
    log("Start Program")

timing.main()导入文件后,从程序中调用。


3

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

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

代码示例如下:

from timeit import default_timer as timer

start= timer()

# Some logic

end = timer()

print("Time taken:", end-start)

timeit在许多情况下,IMO是更好的答案。
马克

3

稍后的答案,但我使用timeit

import timeit
code_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 参数指定代码应重复的次数。
  • 演示版

而且,如果您想计时一些不能放入字符串的代码,该怎么办?
DanielStracaboško,

@daniel您可以创建一个新问题。如果您在此处发布链接,我可能会为您提供帮助。
CONvid19

2

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

  • 可以使用不同的算法评估同一程序
  • 运行时间因算法而异
  • 运行时间因实现而异
  • 运行时间因计算机而异
  • 基于少量输入,运行时间是不可预测的

这是因为最有效的方法是使用“增长顺序”并学习“ O”表示法来正确执行。

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

import time

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

2

您只需在Python中执行此操作即可。无需使其变得复杂。

import time

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

2

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

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

样本输出

Time Taken: 00:00:08

2

首先,通过以管理员身份打开命令提示符(CMD)并在其中键入命令,以安装对人类友好的软件包- pip install humanfriendly

码:

from humanfriendly import format_timespan
import time
begin_time = time.time()
# Put your code here
end_time = time.time() - begin_time
print("Total execution time: ", format_timespan(end_time))

输出:

在此处输入图片说明


1

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

代码如下:

from datetime import timedelta
from monotonic import monotonic

start_time = monotonic()
end_time = monotonic()
print(timedelta(seconds=end_time - start_time))


0

如果要以微秒为单位测量时间,则可以使用以下版本,完全基于Paul McGuireNicojo的回答-这是Python 3代码。我还添加了一些颜色:

import atexit
from time import time
from 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-start
    log("End Program", seconds_to_str(elapsed))


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

log()=>函数,输出定时信息。

txt ==>要记录的第一个参数,以及用来标记时间的字符串。

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

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.