Zaman modülüyle geçen süreyi ölçme


337

Python'daki Zaman modülü ile geçen süreyi ölçmek mümkün mü? Öyleyse, bunu nasıl yaparım?

İmleç belirli bir süre için bir widget varsa, bir olay olur ki bunu yapmak gerekir.


3
Not: kullanarak herhangi bir cevap time.time()yanlış. Bunun en basit örneği, ölçüm süresinde sistem saatinin değişip değişmediğidir.
OrangeDog

Bir imleç bir widget üzerinde belirli bir süre kalırsa bir olayı tetiklemeye ilişkin orijinal sorunuz için docs.python.org/3/library/threading.html ihtiyacınız olan her şeyi sağlıyor. Çoklu iş parçacığı ve zaman aşımı olan bir koşul değişkeni çözümlerden biri olabilir. Bununla birlikte, koşullarınız şu anda cevaplamak için belirsizdir.
Tora

2
time.time()Modern pitonda geçen süreyi ölçmek için kimsenin kullanması için hiçbir neden yoktur (manuel değişiklikler, sapma, artık saniye vb. Etkilenir). Bu sorunun artık geçen süreyi ölçmek için Google'da en iyi sonuç olduğu düşünüldüğünde, aşağıdaki yanıtın daha yüksek olması gerekiyor.
NPras


1
@NPras "modern pitonu unut". Kullanmak her zaman yanlıştı time.time().
OrangeDog

Yanıtlar:


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

Ayrıca çeşitli işlevlerin yürütme süresinin ölçümünü basitleştirmek için basit dekoratör yazabilirsiniz:

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

Kullanımı:

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

Aynı anda birden fazla işlevi tercih edebilirsiniz. Ardından ölçümleri yazdırmak için print_prof_data () öğesini çağırmanız yeterlidir:


11
Ayrıca profil resimlerine pip install profilehooks ve ana sayfasına buradan
bakabilirsiniz

11
Python 3.3'ten bu yana, zaman aşımlarını veya süreleri ölçerken time.monotonic()bunun yerine muhtemelen kullanmanız gerektiğini unutmayın time.time(). docs.python.org/3/library/time.html#time.monotonic
Debilski

39
Burada geçen süre için ölçü biriminin saniye olacağını eklemeye / not etmeye değer.
Eric Kramer

4
@EricKramer teşekkür ederim! ölçüm birimini tanımlamaksızın ölçümleri açıklayan büyük evcil hayvanım. Ve bir .NET adam ilk kez ayak parmaklarını Python içine daldırma, otomatik olarak "milisaniye" düşündüm.
Adam Plocher

2
Sistem saati değiştirilirse (örn.) Çalışmaz ve sonraki çözüme sahip olmayabilir. Doğru cevap: stackoverflow.com/a/47637891/476716
OrangeDog

97

time.time() işi yapacak.

import time

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

elapsed = end - start

Bu soruya bakmak isteyebilirsiniz , ama bunun gerekli olacağını düşünmüyorum.


6
Evet, saniye saniye
Eric Kramer

Start_time değerini start olarak değiştirmelisiniz.
Zoran Pandovski

time.time()kötü bir fikir çünkü sistem saati sıfırlanabilir, bu da zamanda geriye gitmenizi sağlayacaktır. time.monotonic()bununla ilgilenir (monotonik = sadece ileri gider). time.perf_counter()aynı zamanda monotoniktir, ancak daha yüksek bir doğruluğa sahiptir, bu yüzden duvar saati için önerilir.
xjcl

76

Daha iyi biçimlendirme isteyen kullanıcılar için,

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

2 saniye boyunca yazdırılacaktır:

'00:00:02'

ve 7 dakika bir saniye:

'00:07:01'

gmtime ile minimum zaman biriminin saniye olduğunu unutmayın. Mikrosaniyeye ihtiyacınız varsa aşağıdakileri göz önünde bulundurun:

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

strftime belgeleri


1
Bana ilham veren cevabın için teşekkürler. e = time.time() - start_time ; print("%02d:%02d:%02d" % (e // 3600, (e % 3600 // 60), (e % 60 // 1)))24 saatten daha uzun süren durumu kapsayan, neredeyse aynı verimi kullanacağım .
Tora

@ Gelecekte uyumluluk sorunları için% 02d yerine "{}". Biçimine () göz atmak isteyebilirsiniz.
Rutger Hofste

2
teşekkür ederim! Şimdi yenisine alışıyorum. '{: 02d}: {: 02d}: {: 02d}'. Formatı (e // 3600, (e% 3600 // 60), e% 60)
Tora

time.monotonic()diğer cevaplarda olduğu gibi kullanabilir misiniz ?
endolit

elapsed.secondssüre bir günden fazla ise yanlış olur. elapsed.total_seconds()Dirençli olmak istiyorsun
Ash Berlin-Taylor

51

Geçen sürenin en iyi ölçüsü için (Python 3.3'ten beri) kullanın time.perf_counter().

Bir performans sayacının değerini (kesirli saniye cinsinden), yani kısa bir süreyi ölçmek için mevcut en yüksek çözünürlüğe sahip bir saati döndürün. Uyku sırasında geçen süreyi içerir ve sistem çapındadır. Döndürülen değerin referans noktası tanımsızdır, böylece yalnızca ardışık çağrıların sonuçları arasındaki fark geçerlidir.

Saat / gün sırasına göre yapılan ölçümler için ikinci saniyenin altındaki çözünürlükleri umursamıyorsunuz, time.monotonic()bunun yerine kullanın.

Monotonik bir saatin değerini (kesirli saniye cinsinden), yani geriye doğru gidemeyen bir saati döndürün. Saat, sistem saati güncellemelerinden etkilenmez. Döndürülen değerin referans noktası tanımsızdır, böylece yalnızca ardışık çağrıların sonuçları arasındaki fark geçerlidir.

Birçok uygulamada, bunlar aslında aynı şey olabilir.

3.3'ten önce, sıkışıp kaldınız time.clock().

Unix'te, geçerli işlemci süresini saniye cinsinden ifade edilen kayan noktalı sayı olarak döndürün. Kesinlik ve aslında “işlemci zamanı” nın anlamının tanımı, aynı ismin C işlevininkine bağlıdır.

Windows'da, bu işlev, QueryPerformanceCounter () Win32 işlevini temel alarak, kayan nokta sayısı olarak bu işleve yapılan ilk çağrıdan bu yana geçen duvar saati saniye değerini döndürür. Çözünürlük tipik olarak bir mikrosaniyeden daha iyidir.


Python 3.7 Güncellemesi

Python 3.7'deki yenilikler PEP 564 - Nanosaniye çözünürlük ile yeni zaman fonksiyonları ekleyin.

Bunların kullanımı, özellikle çok kısa süreleri ölçüyorsanız veya uygulamanız (veya Windows makineniz) uzun süredir çalışıyorsa, yuvarlama ve kayan nokta hatalarını daha da ortadan kaldırabilir.

Çözünürlük perf_counter()yaklaşık 100 gün sonra bozulmaya başlar . Örneğin, bir yıllık çalışma süresinden sonra, ölçebileceği en kısa aralık (0'dan büyük) başladığı zamandan daha büyük olacaktır.


Python 3.8 Güncellemesi

time.clock artık gitti.


"Birçok uygulamada, bunlar aslında aynı şey olabilir." Doğru, Linux Mint bilgisayarımda time.monotonic () ve time.perf_counter () aynı değerleri döndürüyor gibi görünüyor.
xjcl

7

Daha uzun bir süre.

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

basar

00:03:15

24 saatten fazla ise

25:33:57

Bu Rutger Hofste'nin cevabından ilham alıyor. Teşekkürler Rutger!


6

Saati içe aktarmanız ve ardından geçerli saati bilmek için time.time () yöntemini kullanmanız gerekir.

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

İşleri zamanlamanın bir başka güzel yolu da python yapısıyla kullanmaktır.

ile yapı otomatik çağırıyor __enter__ ve __exit__ tam olarak zaman şeylerin gereken budur yöntemleri.

Bir Timer sınıfı oluşturalım .

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

Sonra Timer sınıfını şu şekilde kullanabilirsiniz:

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

Sonuç şudur:

Asal: [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, 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]

Bazı asal sayıları hesaplamak için geçen süre: 5.01704216003418ms


2

Vadim Shender'ın tepkisi harika. Aşağıdaki gibi daha basit bir dekoratör de kullanabilirsiniz:

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

Programlamada, farklı sonuçlarla zamanı ölçmenin 2 ana yolu vardır :

>>> 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
  • İşlemci Süresi : Bu işlemin CPU üzerinde etkin bir şekilde yürütülmesi için harcanan zamandır. Uyku, bir web isteği beklemek veya yalnızca diğer işlemlerin yürütüldüğü süre buna katkıda bulunmaz.

    • kullanım time.process_time()
  • Duvar Saati Süresi : Bu, "duvarda asılı bir saatte" ne kadar zaman geçtiğini, yani gerçek zamanın dışında olduğunu ifade eder.

    • kullanım time.perf_counter()

      • time.time() Ayrıca duvar saati süresini de ölçer, ancak sıfırlanabilir, böylece zamanda geriye gidebilirsiniz
      • time.monotonic() sıfırlanamaz (monotonik = sadece ileri gider) ancak daha düşük bir hassasiyete sahiptir time.perf_counter()

0

İşte Vadim Shender'ın tablo çıktısı ile akıllı koduna bir güncelleme:

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)
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.