Getting "global name 'foo' is not defined" with Python's timeit - python

I'm trying to find out how much time it takes to execute a Python statement, so I looked online and found that the standard library provides a module called timeit that purports to do exactly that:
import timeit
def foo():
# ... contains code I want to time ...
def dotime():
t = timeit.Timer("foo()")
time = t.timeit(1)
print "took %fs\n" % (time,)
dotime()
However, this produces an error:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 3, in dotime
File "/usr/local/lib/python2.6/timeit.py", line 193, in timeit
timing = self.inner(it, self.timer)
File "<timeit-src>", line 6, in inner
NameError: global name 'foo' is not defined
I'm still new to Python and I don't fully understand all the scoping issues it has, but I don't know why this snippet doesn't work. Any thoughts?

Change this line:
t = timeit.Timer("foo()")
To this:
t = timeit.Timer("foo()", "from __main__ import foo")
Check out the link you provided at the very bottom.
To give the timeit module access to functions you define, you can pass a setup parameter which contains an import statement:
I just tested it on my machine and it worked with the changes.

With Python 3, you can use globals=globals()
t = timeit.Timer("foo()", globals=globals())
From the documentation:
Another option is to pass globals() to the globals parameter, which
will cause the code to be executed within your current global
namespace. This can be more convenient than individually specifying
imports

You can try this hack:
import timeit
def foo():
print 'bar'
def dotime():
t = timeit.Timer("foo()")
time = t.timeit(1)
print "took %fs\n" % (time,)
import __builtin__
__builtin__.__dict__.update(locals())
dotime()

t = timeit.Timer("foo()", "from __main__ import foo")
Since timeit doesn't have your stuff in scope.

add into your setup "import thisfile; "
then when you call the setup function myfunc() use "thisfile.myfunc()"
eg "thisfile.py"
def myfunc():
return 5
def testable(par):
pass
t=timeit.timeit(stmt="testable(v)",setup="import thisfile; v=thisfile.myfunc();").repeat(10)
print( t )

Related

python contextvars pass and access a variable along the chain of calls

Context variables are convenient when we need to pass a variable along the chain of calls so that they share the same context, in the case when this cannot be done through a global variable in the case of concurrency. Context variables can be used as an alternative to global variables both in multi-threaded code and in asynchronous (with coroutines).
I can use contextvars in Python 3.7 and above like below and It's usually really easy:
Sample 1:
import contextvars
user_id = contextvars.ContextVar("user_id")
def f1(user, operation):
user_id.set(user.id)
f2()
def f2():
f3()
def f3():
print(user_id.get()) # gets the user_id value
Sample 2:
But when I am using the contextvars to another module's function it is not accessible, showing below error. It seems I am misunderstanding the usage of contextvars :)
NameError: name 'user_id' is not defined
test2.py
def abc():
print("inside abc")
print(user_id.get())
if __name__=='__main__':
abc()
test1.py
import contextvars
from test2 import abc
import uuid
user_id = contextvars.ContextVar("user_id")
request_id = uuid.uuid4()
def f1():
f2()
def f2():
f3()
def f3():
print("inside f3")
print(user_id.get())
user_id.set(request_id)
f1_calling = f1()
abc_calling = ABC()
Full Output:
inside f3
cdd36594-372d-438a-9bac-da53751af08a
inside abc
Traceback (most recent call last):
File "/var/www/test1.py", line 19, in <module>
abc_calling = abc()
File "/var/www/test2.py", line 3, in abc
print(user_id.get())
NameError: name 'user_id' is not defined
So my fundamental question is how can I pass and access the context variable that I set from one function and access that variable from any sub-function that is called by the main module.?
"Global" variables in Python are not actually global, but are rather attributes of the module that defines them.
You can therefore access a global variable defined in the main module from a sub-module by accessing it as an attribute of sys.modules['__main__']:
test2.py
import sys
def abc():
print("inside abc")
print(sys.modules['__main__'].user_id.get())
Demo: https://replit.com/#blhsing/TurquoiseAltruisticPercent#main.py

Time find of builtin function sum [duplicate]

I'm trying to find out how much time it takes to execute a Python statement, so I looked online and found that the standard library provides a module called timeit that purports to do exactly that:
import timeit
def foo():
# ... contains code I want to time ...
def dotime():
t = timeit.Timer("foo()")
time = t.timeit(1)
print "took %fs\n" % (time,)
dotime()
However, this produces an error:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 3, in dotime
File "/usr/local/lib/python2.6/timeit.py", line 193, in timeit
timing = self.inner(it, self.timer)
File "<timeit-src>", line 6, in inner
NameError: global name 'foo' is not defined
I'm still new to Python and I don't fully understand all the scoping issues it has, but I don't know why this snippet doesn't work. Any thoughts?
Change this line:
t = timeit.Timer("foo()")
To this:
t = timeit.Timer("foo()", "from __main__ import foo")
Check out the link you provided at the very bottom.
To give the timeit module access to functions you define, you can pass a setup parameter which contains an import statement:
I just tested it on my machine and it worked with the changes.
With Python 3, you can use globals=globals()
t = timeit.Timer("foo()", globals=globals())
From the documentation:
Another option is to pass globals() to the globals parameter, which
will cause the code to be executed within your current global
namespace. This can be more convenient than individually specifying
imports
You can try this hack:
import timeit
def foo():
print 'bar'
def dotime():
t = timeit.Timer("foo()")
time = t.timeit(1)
print "took %fs\n" % (time,)
import __builtin__
__builtin__.__dict__.update(locals())
dotime()
t = timeit.Timer("foo()", "from __main__ import foo")
Since timeit doesn't have your stuff in scope.
add into your setup "import thisfile; "
then when you call the setup function myfunc() use "thisfile.myfunc()"
eg "thisfile.py"
def myfunc():
return 5
def testable(par):
pass
t=timeit.timeit(stmt="testable(v)",setup="import thisfile; v=thisfile.myfunc();").repeat(10)
print( t )

Python3-Issue with calling exec(open().read()) inside a function

I'm having an issue with running a python script in a python script that i simply do not understand:
Assume we have 2 files in the same directory: 'init.py' and 'text.py'
init.py:
X = 5
print("init.py was run")
test.py:
exec(open("./init.py").read())
print("X = %s" %X)
If I run test.py now, I get
init.py was run
X = 5
However, if I change test.py into:
def func_call( filename):
exec(open(filename).read())
print("X = %s" %X)
func_call("./init.py")
I get:
init.py was run
Traceback (most recent call last):
File "test.py", line 5, in
func_call("./init.py")
File "test.py", line 3, in func_call
print("X = %s" %X)
NameError: name 'X' is not defined
Can someone explain to me why this leads to different results?
Is there a workaround for this?
My goal is to initializes most of my variables by running a python script and accessing the variables set up in that python script.
According to exec_documentation:
If exec gets two separate objects as globals and locals, the code will be executed as if it were embedded in a class definition.
Inside method globals() and locals() are different objects:
def method():
print(globals() == locals())
exec('X=10')
print('Method execution =', X)
method()
output:
False
NameError: name 'X' is not defined
In global level this objects are equal:
print(globals() == locals())
exec('X=99')
print('Global exec =', X)
Output:
True
Global exec = 99
So If you want to do it via method, you need to pass the same object to exec. For your code it would look like this:
def func_call(filename):
exec(open(filename).read(), globals(), globals())
print("X = %s" %X)
func_call("./init.py")
Nevertheless, as I mentioned in comment, create file with consts and import it. Try to avoid using exec/eval at all costs, unless you are 100% sure what you are doing.

weird behaviour of late import and scopes

I have just discovered this strange scoping behaviour of both Python 2 and 3. When I'm adding a late import for a sub-module, the main import of toplevel module stops working. Viable example:
import os
def start():
import sys
print('in modules?', 'os' in sys.modules)
print('in globals?', 'os' in globals())
print('in locals?', 'os' in locals())
print('os =', os)
import os.path
os.path.exists('useless statement')
start()
The output will be:
in modules? True
in globals? True
in locals? False
Traceback (most recent call last):
File "test.py", line 15, in <module>
start()
File "test.py", line 9, in start
print('os =', os)
UnboundLocalError: local variable 'os' referenced before assignment
Any ideas?
This is nothing special about import statements. It's just how the scoping works in Python. If you're assigning a value to a label, it is local to the scope unless explicitly defined global.
Try this code -
a = 2
def start():
print a
a = 3
start()
This also fails with UnboundLocalError as your code because statement a = 3 makes the label a local to function start.

Is there a way in python to execute all functions in a file without explicitly calling them?

Is there a library or a python magic that allows me to execute all functions in a file without explicitly calling them. Something very similar to what pytest is doing - running all functions that start with 'test_...' without ever registering them anywhere.
For example assume I have a file a.py:
def f1():
print "f1"
def f2():
print "f2"
and assume I have file - my main file - main.py:
if __name__ == '__main__':
some_magic()
so when I call:
python main.py
The output would be:
f1
f2
Here's a way:
def some_magic():
import a
for i in dir(a):
item = getattr(a,i)
if callable(item):
item()
if __name__ == '__main__':
some_magic()
dir(a) retrieves all the attributes of module a. If the attribute is a callable object, call it. This will call everything callable, so you may want to qualify it with and i.startswith('f').
Here's another way:
#!/usr/local/bin/python3
import inspect
import sys
def f1():
print("f1")
def f2():
print("f2")
def some_magic(mod):
all_functions = inspect.getmembers(mod, inspect.isfunction)
for key, value in all_functions:
if str(inspect.signature(value)) == "()":
value()
if __name__ == '__main__':
some_magic(sys.modules[__name__])
It will only call functions that don't have any parameters by using inspect.signature(function).
Have you tried callifile?
pip install callifile
and then, in your file:
from callifile.callifile import callifile as callifile
import sys
callifile(module=sys.modules[__name__], verbose=True)
Self-sufficient example:
In a file some_callify.py:
from callifile.callifile import callifile as callifile
import sys
def f_1():
print "bla"
callifile(module=sys.modules[__name__], verbose=True)
Calling in terminal:
python some_callify.py
Gives me the terminal output:
Apply call_all_function_in_this_file on <module '__main__' from 'some_callify.py'>
See if should call callifile
See if should call f_1
Call f_1
bla

Categories