I am having some trouble with using Popen in my Python project. Basically I have a GUI where a user can type into a Text widget. Upon a button press the text is saved into a new file and then ran as a python file in a subprocess using popen. So basically my GUI acts as sort of a IDE for the user to type in their code, press a "run"-like button and then the script that they typed runs as a subprocess.

Everything works fine, however I am struggling to figure out how to detect syntax errors in the user's code. I have tried to do something like this:

p = subprocess.Popen(cmd)
p.wait()

if p.returncode != 0:
print("Fail")

Without this code my program does as expected and runs the subprocess as long as there are not any syntax errors, however with this, the expected behaviour of the script that the user typed is not done, and the return value is also always 0, regardless of syntax error. I assume this is probably because the thread has executed correctly regardless of what was in it.

I have also tried adding things like:

sys.exit(1)

into the subprocess code to force the script to exit with a specific return code however it still seems to return 0. Again I think this is because sys.exit() only works in the main thread of a program, but I am not sure.

So basically I am trying to figure out a way to make a subprocess' return code a value of not 0 based on it not running properly because of syntax error from the user.

An alternative I guess would be to open a pipe for stderr when I do popen however I do not really need to read what the error message is. My plan was to just bring up some sort of generic error message if somethign was typed incorrectly.

Thank you very much for reading this, sorry if it is confusing.

有帮助吗?

解决方案

Even if you could get this to work, your users are going to hate you for telling them there are syntax errors in their script, but not what or where they are.

So forget about subprocess and use the built-in compile function instead:

    script = 'print(0'
    try:
        compile(script, '<string>', 'exec')
    except SyntaxError as exception:
        # do something user-friendly with exception...
    else:
        # syntax seems okay! run script...

Don't be fooled by the 'exec' argument: this only specifies the kind of code the script contains. If there are no syntax errors, compile returns a code object.

其他提示

From the documentation of sys.exit()

Exit from Python. This is implemented by raising the SystemExit exception, so cleanup actions specified by finally clauses of try statements are honored, and it is possible to intercept the exit attempt at an outer level.

[omissis]

Since exit() ultimately “only” raises an exception, it will only exit the process when called from the main thread, and the exception is not intercepted.

So, you are right that calling sys.exit() will not terminate the process when not in the main thread. Instead of calling sys.exit() you should terminate the thread and signal in some way to the main thread that it has to exit with an error.

However it's not clear from your answer how the threads are organized. In particular the fact that you are using subprocess doesn't have anything to do with the behaviour, as far as I understand at least. If the main thread is running the GUI you should produce a GUI event in order to signal that you want to shut down.

Besides, I really don't get why you have to launch a full-blown process with GUI just to check the syntax. You should have a parser to check that. GUI libraries like Qt provide built-in widgets to handle code highlighting etc.

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top