简体   繁体   中英

Python timeit NameError

I want to use timeit in Python 3.5 to measure two functions. The first one relies on import math and the second one on from math import log2 . I though I can handle this by passing the appropiate import statement as setup string when calling timeit.repeat . But I get NameError: name 'math' is not defined . I don't want to pass the functions as their name strings. When the functions don't depend on imports, this code here works, but I need them with the calls of math.log2

Looking foward to your answers.

def spam_log_v1():
    for _ in range(1000):
        math.log2(2)


def spam_log_v2():
    for _ in range(1000):
        log2(2)


if __name__ == '__main__':

    import timeit

    repeat = 3
    number = 1000
    unit = "usec"
    unittosec = {"usec": 1e6, "msec": 1000, "sec": 1}
    tests = [(spam_log_v1, 'import math'),
             (spam_log_v2, 'from math import log2')]

    for fct, setup in tests:
        res = timeit.repeat(fct, setup=setup, repeat=repeat, number=number)
        print("%s: %d loops, best of %d: %.3g %s per loop" %
              (fct.__name__, number, repeat,
               min(res) / number * unittosec[unit], unit))

The inner function which is run by timeit.repeat looks like this:

def inner(_it, _timer{init}):
    {setup}
    _t0 = _timer()
    for _i in _it:
        {stmt}
    _t1 = _timer()
    return _t1 - _t0

where {setup} is replaced by the setup string and {stmt} is replaced by the statement string. Notice that the setup is run from inside inner . So if you place an import statement in setup , the module name becomes a local variable of inner . Later, when spam_log_v1 is called from the stmt , the module name is not available to spam_log_v1 since the module name is not in the global scope.

The fix is to simply import math and/or from math import log2 at the global level of your script.

import math
from math import log2

def spam_log_v1():
    for _ in range(1000):
        math.log2(2)

def spam_log_v2():
    for _ in range(1000):
        log2(2)

if __name__ == '__main__':
    import timeit
    repeat = 3
    number = 1000
    unit = "usec"
    unittosec = {"usec": 1e6, "msec": 1000, "sec": 1}
    tests = [
        (spam_log_v1, ''),
        (spam_log_v2, '')]

    for fct, setup in tests:
        res = timeit.repeat(fct, setup=setup, repeat=repeat, number=number)
        print("%s: %d loops, best of %d: %.3g %s per loop" %
              (fct.__name__, number, repeat,
               min(res) / number * unittosec[unit], unit))

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM