पायथन समय मापने का कार्य


122

मैं प्रत्येक फ़ंक्शन में बिताए गए समय का परीक्षण करने और उसके समय के साथ उसका नाम प्रिंट करने के लिए एक पायथन फ़ंक्शन बनाना चाहता हूं, मैं फ़ंक्शन नाम कैसे प्रिंट कर सकता हूं और यदि ऐसा करने का कोई अन्य तरीका है, तो कृपया मुझे बताएं

def measureTime(a):
    start = time.clock() 
    a()
    elapsed = time.clock()
    elapsed = elapsed - start
    print "Time spent in (function name) is: ", elapsed

पायथन प्रोफाइलिंग उपकरण आपको हर एक में खर्च किए गए नाम और समय दिखा सकते हैं। यहां पढ़ें: docs.python.org/library/profile.html
रोडमास्टर

timeitमापने के लिए बेहतर उपयोग । यह बिल्कुल सही नहीं है, लेकिन यह दूर से ही आपके छुरा भोंक देता है और timeitखुद को बेहतर बनाने के लिए इसका इस्तेमाल करना ज्यादा आसान है ।

जवाबों:


241

सबसे पहले, मैं अत्यधिक एक उपयोग करने का सुझाव प्रोफाइलर या कम से कम उपयोग timeit

हालाँकि यदि आप सीखने के लिए अपनी स्वयं की समय-सीमा लिखना चाहते हैं, तो यहां एक डेकोरेटर का उपयोग करना शुरू करना है।

अजगर 2:

def timing(f):
    def wrap(*args):
        time1 = time.time()
        ret = f(*args)
        time2 = time.time()
        print '%s function took %0.3f ms' % (f.func_name, (time2-time1)*1000.0)
        return ret
    return wrap

और उपयोग बहुत सरल है, बस @ सजावट सज्जाकार का उपयोग करें:

@timing
def do_work():
  #code

अजगर 3:

def timing(f):
    def wrap(*args, **kwargs):
        time1 = time.time()
        ret = f(*args, **kwargs)
        time2 = time.time()
        print('{:s} function took {:.3f} ms'.format(f.__name__, (time2-time1)*1000.0))

        return ret
    return wrap

नोट: मैं f.func_nameफ़ंक्शन नाम को स्ट्रिंग (पायथन 2 में) के रूप में, या f.__name__ पायथन 3 में प्राप्त करने के लिए कह रहा हूं ।


4
वास्तव में मैं क्या चाहता हूँ :) ... लेकिन आप लोगों ने मुझे अजगर प्रोफाइलर का उपयोग करने के लिए राजी कर लिया
Wazery

3
इस तरह लगता है कि समय () काल के बाद से microseconds में रिपोर्ट करता है? प्रलेखन का कहना है कि यह सेकंड docs.python.org/2/library/time.html#time.time में समय की रिपोर्ट करता है ।
राहुल झा

फंक में उपज का उपयोग करने के बाद, यह प्रभावी नहीं हो सकता है। मैं अभी भी इस पद्धति का उपयोग कैसे कर सकता हूं और उपज का उपयोग कर सकता हूं?
जियामो

डिफ टाइमिंग (एफ): डीप रैप (* आर्ग्स, ** क्वार्ग्स): टाइम १ = टाइम.टाइम () रिट = एफ (* आरजीएस, ** क्वार्ग्स) टाइम २ = टाइम.टाइम () प्रिंट ’% s फंक्शन में% 0.3 लिया गया। f ms '% (f.func_name, (time2-time1) * 1000) रिटर्न रिट रिटर्न रैप
विवेक बागरिया

1
इसे खुद लिखने का नुकसान क्या है? क्या बीते हुए समय की सूची संग्रहीत नहीं की जा रही है और उनके वितरण की जांच काफी सरल है?

51

timeitमॉड्यूल के साथ खेलने के बाद , मुझे इसका इंटरफ़ेस पसंद नहीं है, जो निम्न दो विधि की तुलना में इतना सुंदर नहीं है।

निम्नलिखित कोड पायथन 3 में है।

डेकोरेटर विधि

यह @ माइक की विधि के साथ लगभग समान है। यहां मैं इसे बेहतर बनाने के लिए जोड़ता हूं kwargsऔर functoolsलपेटता हूं ।

def timeit(func):
    @functools.wraps(func)
    def newfunc(*args, **kwargs):
        startTime = time.time()
        func(*args, **kwargs)
        elapsedTime = time.time() - startTime
        print('function [{}] finished in {} ms'.format(
            func.__name__, int(elapsedTime * 1000)))
    return newfunc

@timeit
def foobar():
    mike = Person()
    mike.think(30)

संदर्भ प्रबंधक विधि

from contextlib import contextmanager

@contextmanager
def timeit_context(name):
    startTime = time.time()
    yield
    elapsedTime = time.time() - startTime
    print('[{}] finished in {} ms'.format(name, int(elapsedTime * 1000)))

उदाहरण के लिए, आप इसका उपयोग कर सकते हैं जैसे:

with timeit_context('My profiling code'):
    mike = Person()
    mike.think()

और withब्लॉक के भीतर का कोड टाइम हो जाएगा।

निष्कर्ष

पहली विधि का उपयोग करते हुए, आप सामान्य कोड प्राप्त करने के लिए डेकोरेटर की टिप्पणी कर सकते हैं। हालांकि, यह केवल एक फ़ंक्शन कर सकता है। यदि आपके पास कोड का कुछ हिस्सा है जिसे आप इसे कार्य नहीं बनाते हैं, तो आप दूसरी विधि चुन सकते हैं।

उदाहरण के लिए, अब आपके पास है

images = get_images()
bigImage = ImagePacker.pack(images, width=4096)
drawer.draw(bigImage)

अब आप bigImage = ...लाइन में समय लगाना चाहते हैं । यदि आप इसे किसी फ़ंक्शन में बदलते हैं, तो यह होगा:

images = get_images()
bitImage = None
@timeit
def foobar():
    nonlocal bigImage
    bigImage = ImagePacker.pack(images, width=4096)
drawer.draw(bigImage)

बहुत अच्छा नहीं लग रहा है ... क्या होगा अगर आप पायथन 2 में हैं, जिसमें कोई nonlocalकीवर्ड नहीं है ।

इसके बजाय, दूसरी विधि का उपयोग करना यहाँ बहुत अच्छी तरह से फिट बैठता है:

images = get_images()
with timeit_context('foobar'):
    bigImage = ImagePacker.pack(images, width=4096)
drawer.draw(bigImage)

दिलचस्प योगदान, हालांकि मुझे यह बेकार लगता है कि आपके द्वारा बताए गए डेकोरेटर विधि में, आपको timeitइंटरफ़ेस बदलना और मॉड्यूल के wraps()फ़ंक्शन का उपयोग करना था functools। मेरा मतलब है कि अतिरिक्त कोड आवश्यक नहीं है।
बिलाल बेगेरजाद

1
नीड्सimport functools
ग्वेलियूम शेवेलियर

1
ध्यान दें कि आपका डेकोरेटर मूल फ़ंक्शन का रिटर्न मूल्य खो देता है
मार्क वैन डेले

11

मुझे यह नहीं दिखता कि timeitमॉड्यूल में क्या समस्या है। यह शायद इसे करने का सबसे सरल तरीका है।

import timeit
timeit.timeit(a, number=1)

कार्यों के लिए तर्क भेजना भी संभव है। आपको केवल डेकोरेटर्स का उपयोग करके अपने फ़ंक्शन को लपेटना है। यहाँ और अधिक विवरण: http://www.pythoncentral.io/time-a-python-function/

एक ही मामला है जहाँ आप अपने स्वयं के समय के बयान लिखने में रुचि रखते हैं यदि आप केवल एक बार एक फ़ंक्शन चलाना चाहते हैं और अपना रिटर्न मान भी प्राप्त करना चाहते हैं।

timeitमॉड्यूल का उपयोग करने का लाभ यह है कि यह आपको निष्पादन की संख्या को दोहराता है। यह आवश्यक हो सकता है क्योंकि अन्य प्रक्रियाएं आपके समय की सटीकता के साथ हस्तक्षेप कर सकती हैं। तो, आपको इसे कई बार चलाना चाहिए और सबसे कम मूल्य पर देखना चाहिए।


3
रैपर और डेकोरेटर्स का उपयोग करके फ़ंक्शन के लिए तर्क भेजना? क्यों नहीं timeit.timeit(lambda: func(a,b,c), number=1)? एक टर्मिनल में काल्पनिक समाधान पर परीक्षण करते समय मैं इसका उपयोग करता हूं।
जैक

10

टाइमिट में दो बड़ी खामियां हैं: यह फ़ंक्शन के रिटर्न वैल्यू को वापस नहीं करता है, और यह eval का उपयोग करता है, जिसे आयात के लिए अतिरिक्त सेटअप कोड में पारित करने की आवश्यकता होती है। यह दोनों समस्याओं को हल करती है:

def timed(f):
  start = time.time()
  ret = f()
  elapsed = time.time() - start
  return ret, elapsed

timed(lambda: database.foo.execute('select count(*) from source.apachelog'))
(<sqlalchemy.engine.result.ResultProxy object at 0x7fd6c20fc690>, 4.07547402381897)

धन्यवाद! timeit अपाचे स्पार्क के साथ अच्छी तरह से काम नहीं करता है क्योंकि आपको सभी स्पार्क निर्भरता को आयात करना होगा, और जो एक बड़ी पुरानी स्ट्रिंग बनाना चाहता है जो ऐसा करता है? यह समाधान बहुत सरल और अधिक लचीला है।
पॉल

4

टाइमिंग के लिए एक आसान उपकरण है। https://github.com/RalphMao/PyTimer

यह डेकोरेटर की तरह काम कर सकता है :

from pytimer import Timer
@Timer(average=False)      
def matmul(a,b, times=100):
    for i in range(times):
        np.dot(a,b)        

आउटपुट:

matmul:0.368434
matmul:2.839355

यह नाम स्थान नियंत्रण के साथ प्लग-इन टाइमर की तरह भी काम कर सकता है (यदि आप इसे किसी फ़ंक्शन में सम्मिलित कर रहे हैं जिसमें बहुत सारे कोड हैं और कहीं और भी कॉल किया जा सकता है)।

timer = Timer()                                           
def any_function():                                       
    timer.start()                                         

    for i in range(10):                                   

        timer.reset()                                     
        np.dot(np.ones((100,1000)), np.zeros((1000,500)))
        timer.checkpoint('block1')                        

        np.dot(np.ones((100,1000)), np.zeros((1000,500)))
        np.dot(np.ones((100,1000)), np.zeros((1000,500)))
        timer.checkpoint('block2')                        
        np.dot(np.ones((100,1000)), np.zeros((1000,1000)))

    for j in range(20):                                   
        np.dot(np.ones((100,1000)), np.zeros((1000,500)))
    timer.summary()                                       

for i in range(2):                                        
    any_function()                                        

आउटपुट:

========Timing Summary of Default Timer========
block2:0.065062
block1:0.032529
========Timing Summary of Default Timer========
block2:0.065838
block1:0.032891

आशा है कि यह मदद करेगा


3

डेकोरेटर विधि डेकोरेटर पायथन लाइब्रेरी का उपयोग कर:

import decorator

@decorator
def timing(func, *args, **kwargs):
    '''Function timing wrapper
        Example of using:
        ``@timing()``
    '''

    fn = '%s.%s' % (func.__module__, func.__name__)

    timer = Timer()
    with timer:
        ret = func(*args, **kwargs)

    log.info(u'%s - %0.3f sec' % (fn, timer.duration_in_seconds()))
    return ret

मेरे ब्लॉग पर पोस्ट देखें:

mobilepro.pl ब्लॉग पर पोस्ट करें

Google प्लस पर मेरी पोस्ट


1

इसे करने का मेरा तरीका:

from time import time

def printTime(start):
    end = time()
    duration = end - start
    if duration < 60:
        return "used: " + str(round(duration, 2)) + "s."
    else:
        mins = int(duration / 60)
        secs = round(duration % 60, 2)
        if mins < 60:
            return "used: " + str(mins) + "m " + str(secs) + "s."
        else:
            hours = int(duration / 3600)
            mins = mins % 60
            return "used: " + str(hours) + "h " + str(mins) + "m " + str(secs) + "s."

start = time()फ़ंक्शन / लूप निष्पादित करने से पहले एक चर सेट करें , और printTime(start)ब्लॉक के ठीक बाद।

और आपको जवाब मिल गया।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.