fastero
fastero copied to clipboard
Issue when timing code with a call to global
I tried fastero after listening to the April 28 2022 episode of Python Bytes.
In installed
fastero 0.2.4
python 3.10.4
windows 10.
I wanted to time two functions one that used global and one that didn't.
I made a file - "using_global.py"
R = 8.314
def calling_global():
global R
R*10
calling_global()
and a file - "not_using_global.py"
R=8.314
def not_calling_global():
R*10
not_calling_global()
then at the command line ran:
python -m fastero "file: not_using_global.py" "file: using_global.py"
I received an error
────────────────────────────────────────────────── Benchmark started… ──────────────────────────────────────────────────
Benchmark 1: R = 8.314
def not_calling_global():
R * 10
not_calling_global()
Time (mean ± σ): 196.1 ns ± 5.2 ns
Range (min … max): 190.9 ns … 204.9 ns [runs: 14,000,000]
Benchmark 2: R = 8.314
def calling_global():
global R
R * 10
calling_global()
Traceback (most recent call last):
File "C:\Users\XXX\Anaconda3\envs\eos\lib\site-packages\fastero\core.py", line 475, in app
num_in_one_batch, time_taken = _autorange(timer, autorange_callback)
File "C:\Users\rlarson\Anaconda3\envs\eos\lib\site-packages\fastero\core.py", line 461, in _autorange
time_taken = timer.timeit(number)
File "C:\Users\XXX\Anaconda3\envs\eos\lib\timeit.py", line 178, in timeit
timing = self.inner(it, self.timer)
File "<timeit-src>", line 14, in inner
calling_global()
File "<timeit-src>", line 11, in calling_global
R * 10
NameError: name 'R' is not defined
if I run the file "using_global.py" with python I do not get the error related to this file.
python using_global.py
So after some debugging, I figured out that this is a problem with the python timeit library. If you try the following code:
Expand
import timeit
stmt = '''\
R = 8.314
def calling_global():
global R
R*10
calling_global()'''
timeit.timeit(stmt)
Then it would also raise the same error. But this snippet of code does work:
Expand
import timeit
R = 8.314
def calling_global():
global R
R*10
timeit.timeit(calling_global)
So from this I can say for certain that the issue is with passing a string with code for a function to timeit, but passing the function itself works like expected. I wonder what can I do to fix this 🤔
The underlying code generated by timeit is this:
Expand
def inner(_it, _timer):
pass
_t0 = _timer()
for _i in _it:
R = 8.314
def calling_global():
global R
R*10
calling_global()
_t1 = _timer()
return _t1 - _t0
If you try to execute (inner(range(100), timeit)
) then it would also raise the same error
The reason for this error is that there is no global variable R, only a local variable R that is defined inside a for-loop in the inner
function. So when you're saying global R I guess it doesn't care if it even exists and tries to use a global R and since there isn't a global variable R it fails
In the timeit module near the bottom of the page they have something about using a setup keyword.
def test():
"""Stupid test function"""
L = [i for i in range(100)]
if __name__ == '__main__':
import timeit
print(timeit.timeit("test()", setup="from __main__ import test"))
I was about to make the example work with strings if I used this to import the function through timeit.