การวัดเวลาที่ผ่านไปด้วยโมดูลเวลา


337

ด้วยโมดูล Time ใน python เป็นไปได้หรือไม่ที่จะวัดเวลาที่ผ่านไป? ถ้าเป็นเช่นนั้นฉันจะทำอย่างไร

ฉันต้องทำเช่นนี้เพื่อให้เคอร์เซอร์อยู่ในวิดเจ็ตในช่วงระยะเวลาหนึ่งมีเหตุการณ์เกิดขึ้น


3
โปรดทราบว่าคำตอบใด ๆ ที่ใช้time.time()ไม่ถูกต้อง ตัวอย่างที่ง่ายที่สุดคือถ้าเวลาของระบบเปลี่ยนไปในช่วงระยะเวลาการวัด
OrangeDog

สำหรับคำถามดั้งเดิมของคุณเกี่ยวกับการเริ่มต้นเหตุการณ์หากเคอร์เซอร์อยู่ในช่วงเวลาหนึ่งบนวิดเจ็ตdocs.python.org/3/library/threading.htmlให้สิ่งที่คุณต้องการ การมัลติเธรดและตัวแปรเงื่อนไขที่มีการหมดเวลาอาจเป็นหนึ่งในโซลูชัน อย่างไรก็ตามสถานการณ์ของคุณยังไม่ชัดเจนที่จะตอบ
Tora

2
ไม่มีเหตุผลที่ทุกคนควรใช้time.time()ในการวัดเวลาที่ผ่านไปในไพ ธ อนสมัยใหม่ (ได้รับผลกระทบจากการเปลี่ยนแปลงด้วยตนเองดริฟท์กระโดดวินาที ฯลฯ ) คำตอบด้านล่างนี้จำเป็นต้องสูงขึ้นโดยการพิจารณาคำถามนี้เป็นผลการอันดับต้น ๆ ของ Google ในการวัดเวลาที่ผ่านไป
NPras

คุณสามารถวัดเวลาด้วย cProfile profiler เช่นกัน: docs.python.org/3/library/profile.html#module-cProfile stackoverflow.com/questions/582336/…
Anton Tarasenko

1
@NPras ลืม "modern python" time.time()มันก็มักจะไม่ถูกต้องที่จะใช้
OrangeDog

คำตอบ:


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

คุณยังสามารถเขียนมัณฑนากรอย่างง่ายเพื่อลดความซับซ้อนของการวัดเวลาดำเนินการของฟังก์ชั่นต่างๆ:

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 = {}

การใช้งาน:

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

คุณสามารถโพรไฟล์มากกว่าหนึ่งฟังก์ชั่นพร้อมกัน จากนั้นหากต้องการพิมพ์การวัดเพียงเรียก print_prof_data ():


11
คุณยังสามารถดูprofilehooks pip install profilehooksและโฮมเพจของที่นี่ได้ด้วย
pjama

11
โปรดทราบว่าตั้งแต่ Python 3.3 ควรใช้อย่างใดอย่างหนึ่งtime.monotonic()แล้วtime.time()เมื่อทำการวัดการหมดเวลาหรือระยะเวลา docs.python.org/3/library/time.html#time.monotonic
Debilski

39
ควรเพิ่ม / สังเกตที่นี่ว่าหน่วยการวัดสำหรับเวลาที่ผ่านไปจะเป็นวินาที
Eric Kramer

4
@EricKramer ขอบคุณ! สัตว์เลี้ยงขนาดใหญ่ของฉันอธิบายการวัดโดยไม่ต้องกำหนดหน่วยการวัด และในฐานะที่เป็น. NET ผู้คนจุ่มนิ้วเท้าของเขาใน Python เป็นครั้งแรกฉันคิดว่า "มิลลิวินาที" โดยอัตโนมัติ
Adam Plocher

2
ไม่ทำงานหาก (เช่น) นาฬิการะบบมีการเปลี่ยนแปลงและอาจไม่มีความละเอียดย่อยที่สอง คำตอบที่ถูกต้อง: stackoverflow.com/a/47637891/476716
OrangeDog

97

time.time() จะทำงาน

import time

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

elapsed = end - start

คุณอาจต้องการดูคำถามนี้แต่ฉันไม่คิดว่าจำเป็น


6
ใช่เวลาเป็นวินาที
Eric Kramer

คุณควรเปลี่ยน start เป็น start_time
Zoran Pandovski

time.time()เป็นความคิดที่ไม่ดีเพราะสามารถรีเซ็ตนาฬิการะบบซึ่งจะทำให้คุณย้อนเวลากลับไป time.monotonic()ดูแลสิ่งนี้ (monotonic = ไปข้างหน้าเท่านั้น) time.perf_counter()เป็นแบบโมโนโทนิก แต่ก็มีความแม่นยำสูงกว่าดังนั้นจึงแนะนำให้ใช้เวลานาฬิกาแขวน
xjcl

76

สำหรับผู้ใช้ที่ต้องการการจัดรูปแบบที่ดีกว่า

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

จะพิมพ์ออกมาเป็นเวลา 2 วินาที:

'00:00:02'

และ 7 นาทีหนึ่งวินาที:

'00:07:01'

โปรดทราบว่าหน่วยเวลาขั้นต่ำที่มี gmtime คือวินาที หากคุณต้องการไมโครวินาทีให้พิจารณาสิ่งต่อไปนี้:

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

เอกสารประกอบเบื้องต้น


1
ขอบคุณสำหรับคำตอบซึ่งเป็นแรงบันดาลใจให้ฉัน ฉันจะใช้e = time.time() - start_time ; print("%02d:%02d:%02d" % (e // 3600, (e % 3600 // 60), (e % 60 // 1)))มันให้ผลตอบแทนเกือบเท่ากันและครอบคลุมสถานการณ์ที่ผ่านไปนานกว่า 24 ชั่วโมง
Tora

@Tora คุณอาจต้องการลองใช้ "{}". format () แทนที่จะเป็น% 02d สำหรับปัญหาความเข้ากันได้ในอนาคต
Rutger Hofste

2
ขอบคุณ! ตอนนี้ฉันเริ่มชินกับสิ่งใหม่แล้ว '{: 02d}: {: 02d}: {: 02d}'. รูปแบบ (e // 3600, (e% 3600 // 60), e% 60)
Tora

คุณสามารถใช้time.monotonic()เหมือนคำตอบอื่น ๆ ได้ไหม?
endolith

elapsed.secondsจะไม่ถูกต้องหากระยะเวลามากกว่าหนึ่งวัน คุณต้องการelapsed.total_seconds()ยืดหยุ่น
Ash Berlin-Taylor

51

สำหรับมาตรการที่ดีที่สุดของเวลาที่ผ่านไป (ตั้งแต่ Python 3.3) time.perf_counter()การใช้งาน

ส่งคืนค่า (เป็นเสี้ยววินาที) ของตัวนับประสิทธิภาพเช่นนาฬิกาที่มีความละเอียดสูงสุดที่มีอยู่เพื่อวัดระยะเวลาสั้น ๆ มันรวมถึงเวลาที่ผ่านไประหว่างการนอนหลับและเป็นทั้งระบบ จุดอ้างอิงของค่าที่ส่งคืนนั้นไม่ได้ถูกกำหนดดังนั้นความแตกต่างระหว่างผลลัพธ์ของการโทรติดต่อกันนั้นจะถูกต้อง

สำหรับการวัดตามลำดับชั่วโมง / วันคุณไม่สนใจความละเอียดย่อยวินาทีเพื่อใช้time.monotonic()แทน

คืนค่า (เป็นเสี้ยววินาที) ของนาฬิกาแบบโมโนโทนิคนั่นคือนาฬิกาที่ไม่สามารถย้อนกลับได้ นาฬิกาไม่ได้รับผลกระทบจากการอัพเดตนาฬิการะบบ จุดอ้างอิงของค่าที่ส่งคืนนั้นไม่ได้ถูกกำหนดดังนั้นความแตกต่างระหว่างผลลัพธ์ของการโทรติดต่อกันนั้นจะถูกต้อง

ในการใช้งานหลายอย่างสิ่งเหล่านี้อาจเป็นสิ่งเดียวกัน

ก่อนที่ 3.3 time.clock()คุณติดอยู่กับ

บน Unix ให้ส่งคืนเวลาตัวประมวลผลปัจจุบันเป็นหมายเลขทศนิยมที่แสดงในหน่วยวินาที ความแม่นยำและในความเป็นจริงแล้วคำจำกัดความของความหมายของ“ เวลาตัวประมวลผล” นั้นขึ้นอยู่กับฟังก์ชัน C ในชื่อเดียวกัน

ใน Windows ฟังก์ชั่นนี้จะคืนค่านาฬิกาแขวนวินาทีที่ผ่านไปนับตั้งแต่การโทรครั้งแรกไปยังฟังก์ชั่นนี้เป็นหมายเลขจุดลอยตัวตามฟังก์ชั่น Win32 QueryPerformanceCounter () โดยทั่วไปความละเอียดจะดีกว่าหนึ่งไมโครวินาที


อัพเดทสำหรับ Python 3.7

ใหม่ใน Python 3.7 คือPEP 564 - เพิ่มฟังก์ชั่นเวลาใหม่ด้วยความละเอียดระดับนาโนวินาที

การใช้สิ่งเหล่านี้สามารถกำจัดข้อผิดพลาดในการปัดเศษและทศนิยมโดยเฉพาะอย่างยิ่งหากคุณวัดระยะเวลาสั้นมากหรือแอปพลิเคชันของคุณ (หรือเครื่อง Windows) ใช้งานได้นาน

ความละเอียดจะเริ่มพังลงperf_counter()หลังจากผ่านไปประมาณ 100 วัน ตัวอย่างเช่นหลังจากผ่านไปหนึ่งปีของช่วงเวลาที่สั้นที่สุด (มากกว่า 0) มันสามารถวัดได้จะใหญ่กว่าเมื่อเริ่มต้น


อัพเดทสำหรับ Python 3.8

time.clock หายไปแล้ว


"ในการใช้งานหลายอย่างสิ่งเหล่านี้อาจเป็นสิ่งเดียวกัน" จริงบน Linux Mint PC ของฉัน time.monotonic () และ time.perf_counter () ดูเหมือนจะคืนค่าเหมือนกัน
xjcl

7

เป็นเวลานาน

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

จะพิมพ์

00:03:15

ถ้ามากกว่า 24 ชั่วโมง

25:33:57

นั่นคือแรงบันดาลใจจากคำตอบของ Rutger Hofste ขอบคุณ Rutger!


6

คุณต้องนำเข้าเวลาจากนั้นใช้วิธี time.time () เพื่อทราบเวลาปัจจุบัน

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

อีกวิธีที่ดีในการใช้เวลากับสิ่งนั้นคือใช้กับโครงสร้างของหลาม

ด้วยโครงสร้างจะเรียกเมธอด __enter__และexexit__โดยอัตโนมัติซึ่งเป็นสิ่งที่เราต้องการในเวลา

มาสร้างคลาส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))

จากนั้นเราสามารถใช้คลาส Timer ได้ดังนี้:

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))

ผลที่ได้คือ:

ช่วงเวลา: [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 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 , 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 293, 311, 313, 317, 337, 347, 357, 353, 357, 353 , 379, 383, 389, 397, 401, 409, 419, 421, 431, 433, 439, 443, 449, 457, 461, 463, 467, 479, 487, 491, 499]

เวลาที่ผ่านไปเพื่อคำนวณจำนวนเฉพาะ: 5.01704216003418ms


2

การตอบสนองของ Vadim Shender นั้นยอดเยี่ยม นอกจากนี้คุณยังสามารถใช้มัณฑนากรที่เรียบง่ายเช่นด้านล่าง:

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

ในการเขียนโปรแกรมมี2 วิธีหลักในการวัดเวลาด้วยผลลัพธ์ที่แตกต่าง:

>>> 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
  • เวลาตัวประมวลผล : นี่คือระยะเวลาที่กระบวนการเฉพาะนี้ใช้กับการประมวลผลบน CPU อย่างแข็งขัน สลีปรอการร้องขอจากเว็บหรือเวลาที่ดำเนินการเฉพาะกระบวนการอื่นเท่านั้นที่จะไม่ส่งผลต่อสิ่งนี้

    • ใช้ time.process_time()
  • เวลาของนาฬิกาแขวนผนัง : หมายถึงจำนวนเวลาที่ผ่านไป "บนนาฬิกาที่แขวนอยู่บนกำแพง" เช่นนอกเวลาจริง

    • ใช้ time.perf_counter()

      • time.time() สามารถวัดเวลานาฬิกาปลุกได้ แต่สามารถรีเซ็ตได้ดังนั้นคุณสามารถย้อนเวลากลับไปได้
      • time.monotonic() ไม่สามารถรีเซ็ตได้ (monotonic = เดินหน้าต่อไปเท่านั้น) แต่มีความแม่นยำต่ำกว่า time.perf_counter()

0

นี่คือการอัพเดทรหัสฉลาดของ Vadim Shender พร้อมเอาต์พุตแบบตาราง:

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)
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.