0

I'm currently trying to get attributes of a python stack trace and error from either purely the stderr or intercepting a script and catching its Exception. Either way is fine. This may be an XY problem so alternatives are welcome.

I am currently writing a program that kind of, redirects the arguments to call another python script:

import sys, subprocess
pyargs = sys.argv[1:] # Suppose pyargs is something like ["a.py", "123"]
result = subprocess.run(["python"] + pyargs, stdout=subprocess.PIPE, 
    stderr=subprocess.PIPE)
error = result.stderr # do something with this

Approach 1: Parsing dump

I'm not sure whether there is any existing method that supports either of the two plans. I know that the python error dump is displayed in a very formulaic way:

import sys, traceback
exc_type, exc_value, exc_traceback = sys.exc_info() # shows formatting
traceback.print_exc() # prints the stderr of what we wanted.

And so I thought perhaps we could parse the stderr and see what happens.

Approach 2: Catching exception

I know that we can run subprocess with subprocess.run(..., check=True) to get the subprocess.SubprocessError, but since the subprocess can be anything(not just a python process), we can't actually intercept the actual exception that occurred.

One issue with loading in the python file as a module to this file, is that we cannot supply the necessary arguments, unless we can somehow spoof the sys.argv[] or argparse that's running from the underlying script. Scripts that may have if __name__ == "__main__": will not execute either unless we spoof that too.

Any ideas?

1 Answer 1

2

I prefer approach #2. Whenever possible, I avoid using subprocess or system to call Python from Python.

Changing the value of sys.argv is easy - you just overwrite it using regular assignment.

Tricking the __name__ == "__main__" conditional is harder. Unfortunately, it probably means that you can't simply import the module in the usual way. According to How to import a module as __main__?, you can use the runpy module to execute your module and supply whatever value of __name__ you like.

import runpy
import sys
sys.argv = ["C:/", "foo", "bar"]
try:
    runpy.run_module("yourmodulename", {}, "__main__")
except Exception as e:
    print("caught exception:", e)

Now you can catch any uncaught exceptions that your module throws, and handle them however you like within the except.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.