Mengukur waktu yang berlalu dengan modul Waktu

337

Dengan modul Waktu dalam python apakah mungkin untuk mengukur waktu yang telah berlalu? Jika demikian, bagaimana saya melakukannya?

Saya perlu melakukan ini sehingga jika kursor berada dalam widget untuk jangka waktu tertentu suatu peristiwa terjadi.

persegi panjang
sumber
3
NB bahwa jawaban yang digunakan time.time()salah. Contoh paling sederhana adalah jika waktu sistem berubah selama periode pengukuran.
OrangeDog
Untuk pertanyaan awal Anda tentang memecat suatu acara jika kursor tetap selama beberapa waktu pada sebuah widget, docs.python.org/3/library/threading.html menyediakan semua yang Anda butuhkan, saya pikir. Multithreading dan variabel kondisi dengan batas waktu mungkin menjadi salah satu solusinya. Namun, keadaan Anda saat ini tidak jelas untuk menjawab.
Tora
2
Tidak ada alasan siapa pun harus menggunakan time.time()untuk mengukur waktu yang telah berlalu dalam python modern (dipengaruhi oleh perubahan manual, melayang, detik kabisat dll). Jawaban ini di bawah kebutuhan untuk menjadi lebih tinggi, mengingat pertanyaan ini sekarang hasil teratas di Google untuk mengukur waktu yang telah berlalu.
NPras
Anda dapat mengukur waktu dengan profiler cProfile juga: docs.python.org/3/library/profile.html#module-cProfile stackoverflow.com/questions/582336/…
Anton Tarasenko
1
@NPras lupa "python modern". Itu selalu benar untuk menggunakan time.time().
OrangeDog

Jawaban:

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

Anda juga dapat menulis dekorator sederhana untuk menyederhanakan pengukuran waktu eksekusi berbagai fungsi:

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

Pemakaian:

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

Anda dapat membuat profil lebih dari satu fungsi secara bersamaan. Kemudian untuk mencetak pengukuran cukup panggil print_prof_data ():

Vadim Shender
sumber
11
Anda juga dapat melihat profilhooks pip install profilehooks , dan beranda di sini
pjama
11
Perhatikan bahwa sejak Python 3.3, orang mungkin harus menggunakan time.monotonic()daripada time.time()saat mengukur batas waktu atau durasi. docs.python.org/3/library/time.html#time.monotonic
Debilski
39
Layak ditambahkan / dicatat di sini bahwa satuan ukuran untuk waktu yang berlalu akan menjadi detik.
Eric Kramer
4
@EricKramer terima kasih! hewan peliharaan besar milik saya, menjelaskan pengukuran tanpa menentukan satuan pengukuran. Dan sebagai seorang NET. Pria mencelupkan jari kakinya ke Python untuk pertama kalinya, saya secara otomatis berpikir "milidetik".
Adam Plocher
2
Tidak berfungsi jika (mis.) Jam sistem diubah, dan mungkin tidak memiliki resolusi subsecond. Jawaban yang benar: stackoverflow.com/a/47637891/476716
OrangeDog
97

time.time() akan melakukan pekerjaan.

import time

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

elapsed = end - start

Anda mungkin ingin melihat pertanyaan ini , tetapi saya pikir itu tidak perlu.

lalli
sumber
6
Ya, waktu dalam detik
Eric Kramer
Anda harus mengubah mulai ke start_time.
Zoran Pandovski
time.time()adalah ide yang buruk karena jam sistem dapat diatur ulang yang akan membuat Anda kembali ke masa lalu. time.monotonic()mengurus ini (monoton = hanya berjalan maju). time.perf_counter()juga monoton tetapi memiliki akurasi lebih tinggi, jadi ini direkomendasikan untuk waktu jam dinding.
xjcl
76

Untuk pengguna yang menginginkan pemformatan yang lebih baik,

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

akan dicetak, selama 2 detik:

'00:00:02'

dan selama 7 menit satu detik:

'00:07:01'

perhatikan bahwa satuan waktu minimum dengan gmtime adalah detik. Jika Anda membutuhkan mikrodetik pertimbangkan hal berikut:

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

dokumentasi strftime

Rutger Hofste
sumber
1
Terima kasih atas jawaban Anda, yang menginspirasi saya. Saya akan menggunakan e = time.time() - start_time ; print("%02d:%02d:%02d" % (e // 3600, (e % 3600 // 60), (e % 60 // 1)))hasil yang hampir sama serta mencakup situasi berlalu lebih dari 24 jam.
Tora
@Ora Anda mungkin ingin memeriksa "{}". Format () alih-alih% 02d untuk masalah kompatibilitas di masa mendatang.
Rutger Hofste
2
Terima kasih! Sekarang saya terbiasa dengan yang baru. Format {{: 02d}: {: 02d}: {: 02d} '(e // 3600, (e% 3600 // 60), e% 60)
Tora
dapat Anda gunakan time.monotonic()seperti pada jawaban lainnya?
endolith
elapsed.secondsakan salah jika durasinya lebih dari satu hari. Anda ingin elapsed.total_seconds()menjadi tangguh
Ash Berlin-Taylor
51

Untuk ukuran waktu berlalu terbaik (sejak Python 3.3), gunakan time.perf_counter().

Kembalikan nilai (dalam detik pecahan) penghitung kinerja, yaitu jam dengan resolusi tertinggi yang tersedia untuk mengukur durasi singkat. Itu termasuk waktu yang berlalu selama tidur dan sistem-lebar. Titik referensi dari nilai yang dikembalikan tidak ditentukan, sehingga hanya perbedaan antara hasil panggilan berurutan yang valid.

Untuk pengukuran pada urutan jam / hari, Anda tidak peduli dengan resolusi sub-detik jadi gunakan time.monotonic()saja.

Kembalikan nilai (dalam pecahan detik) dari jam monoton, yaitu jam yang tidak bisa mundur. Jam tidak terpengaruh oleh pembaruan jam sistem. Titik referensi dari nilai yang dikembalikan tidak ditentukan, sehingga hanya perbedaan antara hasil panggilan berurutan yang valid.

Dalam banyak implementasi, ini mungkin sebenarnya hal yang sama.

Sebelum 3.3, Anda terjebak dengan time.clock().

Pada Unix, kembalikan waktu prosesor saat ini sebagai angka titik mengambang yang dinyatakan dalam detik. Ketepatannya, dan pada kenyataannya, definisi sesungguhnya dari "waktu prosesor", tergantung pada fungsi C dari nama yang sama.

Pada Windows, fungsi ini mengembalikan detik jam dinding yang berlalu sejak panggilan pertama ke fungsi ini, sebagai angka titik mengambang, berdasarkan pada fungsi Win32 QueryPerformanceCounter (). Resolusi biasanya lebih baik dari satu mikrodetik.


Perbarui untuk Python 3.7

Baru dalam Python 3.7 adalah PEP 564 - Tambahkan fungsi waktu baru dengan resolusi nanodetik.

Penggunaan ini lebih lanjut dapat menghilangkan kesalahan pembulatan dan titik mengambang, terutama jika Anda mengukur periode yang sangat singkat, atau aplikasi Anda (atau mesin Windows) sudah berjalan lama.

Resolusi mulai mogok perf_counter()setelah sekitar 100 hari. Jadi misalnya setelah satu tahun uptime, interval terpendek (lebih besar dari 0) dapat diukur akan lebih besar daripada ketika dimulai.


Perbarui untuk Python 3.8

time.clock sekarang hilang.

OrangeDog
sumber
"Dalam banyak implementasi, ini mungkin sebenarnya hal yang sama." Benar, pada Linux Mint PC saya, time.monotonic () dan time.perf_counter () tampaknya mengembalikan nilai yang identik.
xjcl
7

Untuk periode yang lebih lama.

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

akan dicetak

00:03:15

jika lebih dari 24 jam

25:33:57

Itu terinspirasi oleh jawaban Rutger Hofste. Rutger terima kasih!

Tora
sumber
6

Anda perlu mengimpor waktu dan kemudian menggunakan metode time.time () untuk mengetahui waktu saat ini.

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 
Nurul Akter Towhid
sumber
3

Cara lain yang bagus untuk mengatur waktu adalah menggunakan struktur dengan python.

dengan struktur secara otomatis memanggil __enter__ dan __exit__ metode yang tepat apa yang kita butuhkan untuk waktu hal.

Mari kita buat kelas 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))

Kemudian, seseorang dapat menggunakan kelas Timer seperti ini:

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

Hasilnya adalah sebagai berikut:

Bilangan Primer: [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 79, 79, 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, 223, 227 , 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 301, 311, 313, 317, 331, 337, 347, 349, 359, 353, 359, 367, 373 , 379, 383, 389, 397, 401, 409, 419, 421, 431, 433, 439, 443, 449, 457, 461, 463, 467, 479, 487, 497, 491, 499]

Waktu yang berlalu untuk menghitung beberapa bilangan prima: 5.01704216003418ms

TM
sumber
2

Tanggapan Vadim Shender sangat bagus. Anda juga dapat menggunakan dekorator sederhana seperti di bawah ini:

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!")
Mohammad
sumber
1

Dalam pemrograman, ada 2 cara utama untuk mengukur waktu , dengan hasil yang berbeda:

>>> 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
  • Waktu Prosesor : Ini adalah berapa lama proses spesifik ini digunakan secara aktif pada CPU. Tidur, menunggu permintaan web, atau waktu ketika hanya proses lain dieksekusi tidak akan berkontribusi untuk ini.

    • Menggunakan time.process_time()
  • Waktu Jam Dinding : Ini mengacu pada berapa banyak waktu yang telah berlalu "pada jam yang tergantung di dinding", yaitu di luar waktu nyata.

    • Menggunakan time.perf_counter()

      • time.time() juga mengukur waktu jam dinding tetapi dapat diatur ulang, sehingga Anda dapat kembali ke masa lalu
      • time.monotonic() tidak dapat diatur ulang (monoton = hanya berjalan maju) tetapi memiliki presisi lebih rendah dari time.perf_counter()
xjcl
sumber
0

Berikut ini adalah pembaruan untuk kode pintar Vadim Shender dengan output tabular:

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