Execute raw Python code in an isolated namespace
Project description
NEval — Namespaced Code Evaluator
This package provides an alternative scoping mechanism
to the standard exec and eval functions for running raw Python code.
The goal is to overcome the following behavior of exec, as described
in the docs:
If
execgets two separate objects asglobalsandlocals, the code will be executed as if it were embedded in a class definition.
For instance, when you want to use locals as the mutable scope and
globals as additional lookup, the default exec and eval procedures
result in unexpected behavior. For example:
# ✓ [1]
exec("a=[1]; print([i for i in a])", {}, {})
# ✗ NameError: name 'a' is not defined
exec("a=[1]; print([i for i in a if a])", {}, {})
# ✓ os
exec("import os; print(os.__name__)", {}, {})
# ✗ NameError: name 'os' is not defined
exec("import os; (lambda: print(os.__name__))()", {}, {})
NEval's alternative evaluation
The main difference is that neval has two arguments called namespace
and namespace_readonly instead of locals and globals. These are similar
to locals and globals but with a slightly different implementation under
the hood to allow for deviations from eval and exec.
Key features of neval include:
namespaceis adictor an object with a__dict__attribute. This object is
read/write in order to reflect all scope changes happening during execution. This is helpful in keeping track of pipelines with many side effects.namespace_readonlyis adictor an object with a__dict__attribute. Note that the dictionary is treated as read-only in the sense that no objects will be added, no objects will be removed, and no objects will be replaced, although objects can be accessed and mutated. A common use case to set this parameter asglobals()to make use of global variables and imported modules without changing the global state.nevalreturns the value of the last section in your code. If the last section is an expression, it will return the executed value, if its a statement (such as assignments of function declarations) it will returnNone.- If an error occurs, a full traceback is generated along with a temporary code file to facilitate the whole process.
- For Python >= 3.11, the traceback also includes a full printout of the code by making
use of the new
Exception.add_notefeature. The aim is to mimic the helpful error feedback ofipython.
File "/temp/neval-057d58343544b6d102cac201bdc11527a0224e87", line 2, in <module>
c = 4/0
~^~
ZeroDivisionError: division by zero
Error in neval-057d58343544b6d102cac201bdc11527a0224e87:
1 a = 1
----> 2 b = 4/0
3 c = 5
Examples
from neval import neval
from types import SimpleNamespace
import numpy
neval("a = 1; b = 2; c = 3; d = 4; a + b + c + d")
# ✓ 10
ns = {}
neval("a = 1; b = 2; c = 3; d = 4; a + b + c + d", ns)
# ✓ 10
ns
# ✓ {'a': 1, 'b': 2, 'c': 3, 'd': 4}
ns = SimpleNamespace()
neval("a = argmax(array([1,2,3,4,3,2,1])**2)", ns, numpy)
ns.a
# ✓ 3
ns = SimpleNamespace()
a, b, c = 1, 2, 3
neval("d = a + b*2 + c*3", ns, globals())
ns.d
# ✓ 14
d
# ✗ NameError: name 'd' is not defined
neval("d = a + b*2 + c*3", globals())
d
# ✓ 14
params = SimpleNamespace(a=1, b=2, c=3)
neval("d = a + b*2 + c*3", params)
params
# ✓ namespace(a=1, b=2, c=3, d=14)
neval("""\
a = 1 + 2
this is incorrect
b = a + 3
""")
# ✗ NameError: name 'this' is not defined
# Error in neval-8efcb70d4b63817f9fd92f3b61eb5a7c0c45cfe9:
# 1 a = 1 + 2
# ----> 2 this is incorrect
# 3 b = a + 3
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file neval-0.0.6.tar.gz.
File metadata
- Download URL: neval-0.0.6.tar.gz
- Upload date:
- Size: 11.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/5.1.1 CPython/3.9.19
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
6a294104f0f577828d1e2e02a56ce2f781861eae48f700359516178a3a751af9
|
|
| MD5 |
562877f48c645229c90f6e180e83efc2
|
|
| BLAKE2b-256 |
4c7725bd298b33b5e7995b0b4382fca878cfea316ff6fbccf66a8b29039f844a
|
File details
Details for the file neval-0.0.6-py3-none-any.whl.
File metadata
- Download URL: neval-0.0.6-py3-none-any.whl
- Upload date:
- Size: 7.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/5.1.1 CPython/3.9.19
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
645fd3735b02b8546e57e71323503d036ae4d14439578febfa6d3c93bb227f5b
|
|
| MD5 |
758d2592ec80b063e0978588a7a91cf3
|
|
| BLAKE2b-256 |
f0bfb240e2ffa921554ae9cc89069b056a46f1418aa94320100cbe956dacab5b
|