I have a python script that reads some input, generates a python script, and then runs the generated script. What I would like is that if there are errors in the generated script, they are reported at the file/lineno of the input file, not in the generated script.
If python supported a #line directive as in C or perl, I'd just put those in the generated script, and that would be all I needed. It doesn't look like that is supported, however.
I tried having my generated script sit in a try block, with the idea that I could catch exceptions and use the traceback module to tweak how the stack trace is printed. The problem is that the most common type of error is a parse error, and those seem to happen and get reported outside my control (i.e., the exception is thrown before the try, so my exception handler is never invoked).
The best bet I've been able to come up with is to use compile() on my generated script and then try to catch errors. That looks like it would force me to slurp in my entire generated script as a string (which could be large), though. Also, what I really want is to be able to run the generated script in its own sandbox, so it's not affected at all by the calling script (if not for error reporting, I would invoke the script as a new python process). If I use compile/exec, it's unclear to me that would be the case. Would passing an empty dictionary for the globals argument of exec() do the trick?
Is there a better way to do this sort of thing?
Edit:
The generated script could be almost anything. The input file allows the user to insert arbitrary python code in the generated script. What I'd like to do is generate a script like:
temp.py:
#line 10 original_file
for i in range(0,3)::
and have the syntax error be reported on line 10 of "original_file" and not line 2 of temp.py (which would mean nothing to the user).
The best I have so far is to insert #line directives in the generated script and have have the original script (i.e., the one that generated temp.py) execute the generated script as:
import runpy
try:
runpy.run_path(generated_file)
except:
print_stack_trace(traceback.format_exc(), generated_file)
The "print_stack_trace()" function parses the traceback and uses the #line directives to translate back to the original source.
This seems to work okay for simple cases, but I'm not sure of the implications of running the generated script (whose contents are arbitrary) in the same python that is running my generator script.