Đo thời gian đã trôi qua với mô-đun Thời gian


337

Với mô-đun Time trong python, có thể đo thời gian trôi qua không? Nếu vậy, làm thế nào để tôi làm điều đó?

Tôi cần phải làm điều này để nếu con trỏ đã ở trong một widget trong một thời gian nhất định thì một sự kiện sẽ xảy ra.


3
NB rằng bất kỳ câu trả lời sử dụng time.time()là không chính xác. Ví dụ đơn giản nhất là nếu thời gian hệ thống bị thay đổi trong khoảng thời gian đo.
OrangeDog

Đối với câu hỏi ban đầu của bạn về việc bắn một sự kiện nếu con trỏ duy trì trong một thời gian nhất định trên một tiện ích, docs.python.org/3/l Library / thereading.html cung cấp tất cả những gì bạn cần, tôi nghĩ vậy. Đa luồng và một biến điều kiện có thời gian chờ có thể là một trong những giải pháp. Hoàn cảnh của bạn, tuy nhiên, hiện không rõ ràng để trả lời.
Tora

2
Không có lý do gì bất cứ ai nên sử dụng time.time()để đo thời gian trôi qua trong con trăn hiện đại (bị ảnh hưởng bởi thay đổi thủ công, trôi dạt, giây nhuận, v.v.). Câu trả lời dưới đây cần phải cao hơn, vì câu hỏi này hiện là kết quả hàng đầu trong Google để đo thời gian trôi qua.
NPras

Bạn cũng có thể đo thời gian với trình biên dịch cProfile: docs.python.org/3/l Library / profile.html #
Anton Tarasenko

1
@NPras quên "trăn hiện đại". Nó luôn luôn không chính xác để sử dụng time.time().
OrangeDog

Câu trả lời:


514
start_time = time.time()
# your code
elapsed_time = time.time() - start_time

Bạn cũng có thể viết trình trang trí đơn giản để đơn giản hóa việc đo thời gian thực hiện của các chức năng khác nhau:

import time
from functools import wraps

PROF_DATA = {}

def profile(fn):
    @wraps(fn)
    def with_profiling(*args, **kwargs):
        start_time = time.time()

        ret = fn(*args, **kwargs)

        elapsed_time = time.time() - start_time

        if fn.__name__ not in PROF_DATA:
            PROF_DATA[fn.__name__] = [0, []]
        PROF_DATA[fn.__name__][0] += 1
        PROF_DATA[fn.__name__][1].append(elapsed_time)

        return ret

    return with_profiling

def print_prof_data():
    for fname, data in PROF_DATA.items():
        max_time = max(data[1])
        avg_time = sum(data[1]) / len(data[1])
        print "Function %s called %d times. " % (fname, data[0]),
        print 'Execution time max: %.3f, average: %.3f' % (max_time, avg_time)

def clear_prof_data():
    global PROF_DATA
    PROF_DATA = {}

Sử dụng:

@profile
def your_function(...):
    ...

Bạn có thể cấu hình nhiều hơn một chức năng cùng một lúc. Sau đó, để in các phép đo, chỉ cần gọi print_prof_data ():


11
Bạn cũng có thể xem sơ lược về hồ sơ pip install profilehookstrang chủ
pjama

11
Lưu ý rằng kể từ Python 3.3, có lẽ người ta nên sử dụng time.monotonic()thay vì time.time()khi đo thời gian chờ hoặc thời lượng. docs.python.org/3/library/time.html#time.monotonic
Debilski

39
Đáng để thêm / lưu ý ở đây rằng đơn vị đo thời gian đã trôi qua sẽ là giây.
Eric Kramer

4
@EricKramer cảm ơn bạn! thú cưng khổng lồ của tôi, giải thích các phép đo mà không xác định đơn vị đo. Và khi một anh chàng .NET lần đầu tiên nhúng ngón chân vào Python, tôi tự động nghĩ "mili giây".
Adam Plocher

2
Không hoạt động nếu (ví dụ) đồng hồ hệ thống bị thay đổi và có thể không có độ phân giải thứ hai. Câu trả lời đúng: stackoverflow.com/a/47637891/476716
OrangeDog

97

time.time() sẽ làm việc

import time

start = time.time()
# run your code
end = time.time()

elapsed = end - start

Bạn có thể muốn xem xét câu hỏi này , nhưng tôi không nghĩ nó sẽ cần thiết.


6
Vâng, thời gian tính bằng giây
Eric Kramer

Bạn nên thay đổi bắt đầu thành start_time.
Zoran Pandovski

time.time()là một ý tưởng tồi vì đồng hồ hệ thống có thể được thiết lập lại sẽ khiến bạn quay ngược thời gian. time.monotonic()quan tâm đến điều này (đơn điệu = nó chỉ đi về phía trước). time.perf_counter()cũng đơn điệu nhưng có độ chính xác cao hơn, vì vậy điều này được khuyến nghị cho thời gian đồng hồ treo tường.
xjcl

75

Đối với người dùng muốn định dạng tốt hơn,

import time
start_time = time.time()
# your script
elapsed_time = time.time() - start_time
time.strftime("%H:%M:%S", time.gmtime(elapsed_time))

sẽ in ra, trong 2 giây:

'00:00:02'

và trong 7 phút một giây:

'00:07:01'

lưu ý rằng đơn vị thời gian tối thiểu với gmtime là giây. Nếu bạn cần micro giây, hãy xem xét những điều sau:

import datetime
start = datetime.datetime.now()
# some code
end = datetime.datetime.now()
elapsed = end - start
print(elapsed)
# or
print(elapsed.seconds,":",elapsed.microseconds) 

tài liệu strftime


1
Cảm ơn bạn đã trả lời của bạn, mà truyền cảm hứng cho tôi. Tôi sẽ sử dụng e = time.time() - start_time ; print("%02d:%02d:%02d" % (e // 3600, (e % 3600 // 60), (e % 60 // 1)))năng suất đó gần như tương tự cũng như bao quát tình huống trôi qua hơn 24 giờ.
Tora

@Tora bạn có thể muốn kiểm tra "{}". Format () thay vì% 02d cho các vấn đề tương thích trong tương lai.
Rutger Hofste

2
cảm ơn bạn! Bây giờ tôi đã quen với cái mới. Định dạng '{: 02d}: {: 02d}: {: 02d}'. (E // 3600, (e% 3600 // 60), e% 60)
Tora

bạn có thể sử dụng time.monotonic()như trong các câu trả lời khác?
endolith

elapsed.secondssẽ không chính xác nếu thời lượng lớn hơn một ngày. Bạn muốn elapsed.total_seconds()kiên cường
Ash Berlin-Taylor

51

Để đo thời gian trôi qua tốt nhất (kể từ Python 3.3), hãy sử dụng time.perf_counter().

Trả về giá trị (tính bằng giây) của bộ đếm hiệu suất, tức là đồng hồ có độ phân giải cao nhất có sẵn để đo thời lượng ngắn. Nó bao gồm thời gian trôi qua trong khi ngủ và toàn hệ thống. Điểm tham chiếu của giá trị trả về là không xác định, do đó chỉ có sự khác biệt giữa kết quả của các cuộc gọi liên tiếp là hợp lệ.

Đối với các phép đo theo thứ tự giờ / ngày, bạn không quan tâm đến độ phân giải dưới giây, vì vậy hãy sử dụng time.monotonic()thay thế.

Trả về giá trị (tính bằng giây) của đồng hồ đơn điệu, tức là đồng hồ không thể lùi lại. Đồng hồ không bị ảnh hưởng bởi cập nhật đồng hồ hệ thống. Điểm tham chiếu của giá trị trả về là không xác định, do đó chỉ có sự khác biệt giữa kết quả của các cuộc gọi liên tiếp là hợp lệ.

Trong nhiều triển khai, đây thực sự có thể là điều tương tự.

Trước 3.3, bạn bị mắc kẹt với time.clock().

Trên Unix, trả về thời gian của bộ xử lý hiện tại dưới dạng số dấu phẩy động được biểu thị bằng giây. Độ chính xác, và trên thực tế, chính là định nghĩa về ý nghĩa của thời gian xử lý của bộ xử lý thời gian, phụ thuộc vào chức năng C cùng tên.

Trên Windows, hàm này trả về số giây đồng hồ treo tường đã trôi qua kể từ lần gọi đầu tiên đến hàm này, dưới dạng số dấu phẩy động, dựa trên hàm Win32 QueryPerformanceCorer (). Độ phân giải thường tốt hơn một micro giây.


Cập nhật cho Python 3.7

Điểm mới trong Python 3.7 là PEP 564 - Thêm các hàm thời gian mới với độ phân giải nano giây.

Việc sử dụng chúng có thể loại bỏ thêm các lỗi làm tròn và dấu phẩy động, đặc biệt là nếu bạn đo các khoảng thời gian rất ngắn hoặc ứng dụng của bạn (hoặc máy Windows) hoạt động lâu.

Nghị quyết bắt đầu bị phá vỡ perf_counter()sau khoảng 100 ngày. Vì vậy, ví dụ sau một năm thời gian hoạt động, khoảng thời gian ngắn nhất (lớn hơn 0) nó có thể đo sẽ lớn hơn so với khi bắt đầu.


Cập nhật cho Python 3.8

time.clock bây giờ đã biến mất


"Trong nhiều triển khai, đây thực sự có thể là điều tương tự." Đúng, trên Linux Mint PC của tôi, time.monotonic () và time.perf_corer () dường như trả về các giá trị giống hệt nhau.
xjcl

7

Trong một thời gian dài hơn.

import time
start_time = time.time()
...
e = int(time.time() - start_time)
print('{:02d}:{:02d}:{:02d}'.format(e // 3600, (e % 3600 // 60), e % 60))

sẽ in

00:03:15

nếu hơn 24 giờ

25:33:57

Điều đó được lấy cảm hứng từ câu trả lời của Rutger Hofste. Cảm ơn bạn


6

Bạn cần nhập thời gian và sau đó sử dụng phương thức time.time () để biết thời gian hiện tại.

import time

start_time=time.time() #taking current time as starting time

#here your code

elapsed_time=time.time()-start_time #again taking current time - starting time 

3

Một cách tốt đẹp để thời gian điều là sử dụng với cấu trúc python.

với cấu trúc đang tự động gọi các phương thức __enter____exit__ , đó chính xác là những gì chúng ta cần để tính thời gian.

Hãy tạo một lớp Timer .

from time import time

class Timer():
    def __init__(self, message):
        self.message = message
    def __enter__(self):
        self.start = time()
        return None  # could return anything, to be used like this: with Timer("Message") as value:
    def __exit__(self, type, value, traceback):
        elapsed_time = (time() - self.start) * 1000
        print(self.message.format(elapsed_time))

Sau đó, người ta có thể sử dụng lớp Timer như thế này:

with Timer("Elapsed time to compute some prime numbers: {}ms"):
    primes = []
    for x in range(2, 500):
        if not any(x % p == 0 for p in primes):
            primes.append(x)
    print("Primes: {}".format(primes))

Kết quả là như sau:

Số nguyên tố: [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 89 , 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 227 , 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307, 311, 313, 317, 331, 337, 347, 349, 353, 359, 367, 373 , 379, 383, 389, 397, 401, 409, 419, 421, 431, 433, 439, 443, 449, 457, 461, 463, 467, 479, 487, 491, 499]

Thời gian đã trôi qua để tính một số số nguyên tố: 5,01704216003418ms


2

Phản ứng của Gulim Shender là tuyệt vời. Bạn cũng có thể sử dụng một trang trí đơn giản hơn như dưới đây:

import datetime
def calc_timing(original_function):                            
    def new_function(*args,**kwargs):                        
        start = datetime.datetime.now()                     
        x = original_function(*args,**kwargs)                
        elapsed = datetime.datetime.now()                      
        print("Elapsed Time = {0}".format(elapsed-start))     
        return x                                             
    return new_function()  

@calc_timing
def a_func(*variables):
    print("do something big!")

1

Trong lập trình, có 2 cách chính để đo thời gian , với các kết quả khác nhau:

>>> print(time.process_time()); time.sleep(10); print(time.process_time())
0.11751394000000001
0.11764988400000001  # took  0 seconds and a bit
>>> print(time.perf_counter()); time.sleep(10); print(time.perf_counter())
3972.465770326
3982.468109075       # took 10 seconds and a bit
  • Thời gian xử lý : Đây là khoảng thời gian quy trình cụ thể này dành tích cực được thực thi trên CPU. Ngủ, chờ yêu cầu web hoặc thời gian khi chỉ các quy trình khác được thực thi sẽ không đóng góp cho việc này.

    • Sử dụng time.process_time()
  • Thời gian trên đồng hồ treo tường: Điều này đề cập đến thời gian đã trôi qua "trên đồng hồ treo trên tường", tức là ngoài thời gian thực.

    • Sử dụng time.perf_counter()

      • time.time() cũng đo thời gian đồng hồ treo tường nhưng có thể được đặt lại, vì vậy bạn có thể quay ngược thời gian
      • time.monotonic() không thể được đặt lại (đơn điệu = chỉ đi tiếp) nhưng có độ chính xác thấp hơn time.perf_counter()

0

Dưới đây là bản cập nhật cho mã thông minh của Vadim Shender với đầu ra dạng bảng:

import collections
import time
from functools import wraps

PROF_DATA = collections.defaultdict(list)

def profile(fn):
    @wraps(fn)
    def with_profiling(*args, **kwargs):
        start_time = time.time()
        ret = fn(*args, **kwargs)
        elapsed_time = time.time() - start_time
        PROF_DATA[fn.__name__].append(elapsed_time)
        return ret
    return with_profiling

Metrics = collections.namedtuple("Metrics", "sum_time num_calls min_time max_time avg_time fname")

def print_profile_data():
    results = []
    for fname, elapsed_times in PROF_DATA.items():
        num_calls = len(elapsed_times)
        min_time = min(elapsed_times)
        max_time = max(elapsed_times)
        sum_time = sum(elapsed_times)
        avg_time = sum_time / num_calls
        metrics = Metrics(sum_time, num_calls, min_time, max_time, avg_time, fname)
        results.append(metrics)
    total_time = sum([m.sum_time for m in results])
    print("\t".join(["Percent", "Sum", "Calls", "Min", "Max", "Mean", "Function"]))
    for m in sorted(results, reverse=True):
        print("%.1f\t%.3f\t%d\t%.3f\t%.3f\t%.3f\t%s" % (100 * m.sum_time / total_time, m.sum_time, m.num_calls, m.min_time, m.max_time, m.avg_time, m.fname))
    print("%.3f Total Time" % total_time)
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.