I would like to handle a NameError
exception by injecting the desired missing variable into the frame and then continue the execution from last attempted instruction.
The following pseudo-code should illustrate my needs.
def function():
return missing_var
try:
print function()
except NameError:
frame = inspect.trace()[-1][0]
# inject missing variable
frame.f_globals["missing_var"] = ...
# continue frame execution from last attempted instruction
exec frame.f_code from frame.f_lasti
Read the whole unittest on repl.it
The code runs in a slave process, which is controlled by a parent. Tasks (functions really) are written in the parent and latter passed to the slave using dill. I expect some tasks (running in the slave process) to try to access variables from outer scopes in the parent and I'd like the slave to request those variables to the parent on the fly.
p.s.: I don't expect this magic to run in a production environment.
Perhaps after the first for-loop, add the try/except . Then if an error is raised, it will continue with the next file. This is a perfect example of why you should use a with statement here to open files. When you open the file using open() , but an error is catched, the file will remain open forever.
The idea of exception handling (often called "Structured Exception Handling") is that your application instals one or more callback routines called "exception handlers" at run-time and then, if an exception occurs, the system will call the routine to let the application deal with the exception.
On the contrary to what various commenters are saying, "resume-on-error" exception handling is possible in Python. The library fuckit.py
implements said strategy. It steamrollers errors by rewriting the source code of your module at import time, inserting try...except
blocks around every statement and swallowing all exceptions. So perhaps you could try a similar sort of tactic?
It goes without saying: that library is intended as a joke. Don't ever use it in production code.
You mentioned that your use case is to trap references to missing names. Have you thought about using metaprogramming to run your code in the context of a "smart" namespace such as a defaultdict
? (This is perhaps only marginally less of a bad idea than fuckit.py
.)
from collections import defaultdict
class NoMissingNamesMeta(type):
@classmethod
def __prepare__(meta, name, bases):
return defaultdict(lambda: "foo")
class MyClass(metaclass=NoMissingNamesMeta):
x = y + "bar" # y doesn't exist
>>> MyClass.x
'foobar'
NoMissingNamesMeta
is a metaclass - a language construct for customising the behaviour of the class
statement. Here we're using the __prepare__
method to customise the dictionary which will be used as the class's namespace during creation of the class. Thus, because we're using a defaultdict
instead of a regular dictionary, a class whose metaclass is NoMissingNamesMeta
will never get a NameError
. Any names referred to during the creation of the class will be auto-initialised to "foo"
.
This approach is similar to @AndréFratelli's idea of manually requesting the lazily-initialised data from a Scope
object. In production I'd do that, not this. The metaclass version requires less typing to write the client code, but at the expense of a lot more magic. (Imagine yourself debugging this code in two years, trying to understand why non-existent variables are dynamically being brought into scope!)
The "resumption" exception handling technique has proven to be problematic, that's why it's missing from C++ and later languages.
Your best bet is to use a while
loop to not resume where the exception was thrown but rather repeat from a predetermined place:
while True:
try:
do_something()
except NameError as e:
handle_error()
else:
break
You really can't unwind the stack after an exception is thrown, so you'd have to deal with the issue before hand. If your requirement is to generate these variables on the fly (which wouldn't be recommended, but you seem to understand that), then you'd have to actually request them. You can implement a mechanism for that (such as having a global custom Scope
class instance and overriding __getitem__
, or using something like the __dir__
function), but not as you are asking for it.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With