Why doesn't exec work in a function with a subfunction?
Correct. You can't use exec in a function that has a subfunction, unless you specify a context. From the docs:
If exec is used in a function and the
function contains a nested block with
free variables, the compiler will
raise a SyntaxError unless the exec
explicitly specifies the local
namespace for the exec. (In other
words, "exec obj" would be illegal,
but "exec obj in ns" would be legal.)
There is good reason for this which I would probably understand if it wasn't Sunday night.
Now, next question: Why are you using exec? It's very rarely needed. You say you have a good reason. I'm feeling sceptical about that. ;) If you have a good reason I'll tell you the workaround. :-P
Oh well, here it is anyway:
def test2():
"""Test with a subfunction."""
exec 'print "hi from test2"' in globals(), locals()
def subfunction():
return True
Workaround for subfunction defined in exec() inside of a function
There's no need to create the function dynamically and use exec
. Just iterate over xdat
.
def fitFunc(xdat, a, b):
return (a/ps) * sum(x**b for x in xdat)
Exec doesn't work with functions and variables
Let me give a simple example of what I was telling you in the comments. This is my folder structure:
/sample
- plugins/
- __init__.py # not necessary, but maybe you want to apply some logic
# before importing the plugins
- plugin1.py
- plugin2.py
- plugin3.py
- __init__.py
- test.py
Every plugin prints what plugins it is (e.g., print('plugin 1')
). test.py
is as follows:
import os
if __name__ == '__main__':
# load plugins
plugins = [p for p in os.listdir('plugins') if not p.startswith('_')]
for p in plugins:
__import__('plugins.'+p[:-3])
The output is:
plugin 1
plugin 2
plugin 3
Which means I successfully imported all those modules (plugins) by using __import__
. Note that __import__
returns a reference to the imported module, so you can store it for later manipulation. Hope it helps!
Why am I getting errors with execs nested in functions?
The answer, as said in this question, is the lack of context. I wanted exec code in locals(), globals()
Exec in Python 2.7.6
You can't use exec in a function that has a subfunction, unless you specify a context. From the docs:
If exec is used in a function and the function contains a nested block
with free variables, the compiler will raise a SyntaxError unless the
exec explicitly specifies the local namespace for the exec. (In other
words, "exec obj" would be illegal, but "exec obj in ns (namespace)" would be
legal.)
Here is the code to implement exec
:
def test2():
"""Test with a subfunction."""
exec 'print "hi from test2"' in globals(), locals()
def subfunction():
return True
test2()
This example was taken from: In Python, why doesn't exec work in a function with a subfunction?
Why doesn't exec(break) work inside a while loop
This is because exec()
is ignorant to your surrounding while loop. So the only statement that exec()
sees in your example is break
. Instead of using exec("break")
, simply use break
as is.
The only access the exec()
function has to its surrounding scope, is the globals()
and locals()
dictionaries. The documentation for exec()
provides some insight into how exec()
works:
This function supports dynamic execution of Python code. object must be either a string or a code object. If it is a string, the string is parsed as a suite of Python statements which is then executed (unless a syntax error occurs). [1] If it is a code object, it is simply executed. In all cases, the code that’s executed is expected to be valid as file input (see the section “File input” in the Reference Manual). Be aware that the return and yield statements may not be used outside of function definitions even within the context of code passed to the exec() function. The return value is None.
In all cases, if the optional parts are omitted, the code is executed in the current scope. If only globals is provided, it must be a dictionary, which will be used for both the global and the local variables. If globals and locals are given, they are used for the global and local variables, respectively. If provided, locals can be any mapping object. Remember that at module level, globals and locals are the same dictionary. If exec gets two separate objects as globals and locals, the code will be executed as if it were embedded in a class definition.
If the globals dictionary does not contain a value for the key builtins, a reference to the dictionary of the built-in module builtins is inserted under that key. That way you can control what builtins are available to the executed code by inserting your own builtins dictionary into globals before passing it to exec().
Python problem with function declaration inside exec
TLDR: Provide explicit globals dictionaries to execute code "as if" it were run at top-level.
Python uses lexical scoping, which roughly means that names are looked up as per the nesting in source code. For example, a nested function can access an outer function's variable.
def foo():
bar = 12
def qux():
print(bar) # nested scope accesses outer scope
return qux
Notably, this kind of name lookup happens at source code compilation time – the compiler knows that both foo
and qux
access bar
, so it must be made available to both. The inner function is directly compiled to look at the variable of the outer function.
If instead a function is not nested, its name lookup to non-local variables automatically goes to global scope.
def qux():
print(bar) # top-level scope accesses global scope
This is a problem when we exec
code in a function: A definition such as def main(): this()
is compiled to lookup this
at global scope, but exec
runs in the current local scope of the function.
In all cases, if the optional parts are omitted, the code is executed in the current scope.
Thus, this
is looked up globally but defined locally.1 The compiler parses def test
and the exec code separately, so it does not know that lookups are meant to be treated as nested.
As a result, the lookup fails.
In order to exec
code "as if" it were run at top-level, it is sufficient to supply an explicit globals
– for example a fresh namespace {}
or the actual globals()
.
def test():
exec("""
def this():
print('this')
def main():
this()
main()
""", {})
# ^^ globals namespace for exec
test()
This means the code is now run in (its own) global namespace, which is where the lookup of functions searches as well.
1This can be checked by printing globals()
/locals()
and by inspecting the instructions of the function. dis.dis(main)
in the exec would produce:
6 0 LOAD_GLOBAL 0 (this)
2 CALL_FUNCTION 0
4 POP_TOP
6 LOAD_CONST 0 (None)
8 RETURN_VALUE
exec() not working inside function python3.x
Instead of using exec
with function names, just keep the function objects in the list:
fn_lst = [has_at, has_num, ...]
and perform the call directly:
def abc(xyz):
for i in fn_lst:
temp= i(xyz)
print(temp)
Why doesn't an import in an exec in a function work?
How about this:
def test():
exec (code, globals())
f()
Related Topics
Setting Django Up to Use MySQL
Substitute Multiple Whitespace with Single Whitespace in Python
How to Form Tuple Column from Two Columns in Pandas
Tensorflow: How to Replace or Modify Gradient
Group Duplicate Column Ids in Pandas Dataframe
Class Inheritance in Python 3.7 Dataclasses
How to Use Win32 API with Python
How to Edit a Seaborn Legend Title and Labels for Figure-Level Functions
Unique Combinations of Values in Selected Columns in Pandas Data Frame and Count
Is the Shortcircuit Behaviour of Python's Any/All Explicit
Using Cprofile Results with Kcachegrind
Solving Embarassingly Parallel Problems Using Python Multiprocessing
Using Lxml and Iterparse() to Parse a Big (+- 1Gb) Xml File
Writing Utf-8 String to MySQL with Python
How to Write Tests for the Argparse Portion of a Python Module