-1
from PyQt6.QtWidgets import QMainWindow
from PyQt6.QtCore import  QThread

class Window_dev(QMainWindow):

    def __init__(self):
        super(Window_dev, self).__init__()

        self.initUI()

    def initUI(self):

        self.thread()
        self.worker = WorkerThread()
        self.worker.start()
        self.show()

class WorkerThread1(QThread):
   def run(self):       
       try:
           os.system("python server.py")
       except Exception as err:
           print(err)

def main():

    app = QApplication(sys.argv)
    ex = Window_dev()
    sys.exit(app.exec())


if __name__ == '__main__':
    main()

When server.py encounters an error and crashes, the error should be captured by my python program. When I run this nothing is being caught.

sorry, this was closed by the admins because they think that there is no solution but there is a solution. here is the solution for everyone's benefit:

import sys

from PyQt5.QtCore import QProcess
from PyQt5.QtWidgets import QApplication, QMainWindow, QAction, QFileDialog, QTextEdit, QVBoxLayout, QWidget

class MainWindow(QMainWindow):
    def __init__(self, parent=None):
        super().__init__(parent)

        # Create a "Open File" action with a keyboard shortcut
        open_file_action = QAction('Open File', self)
        open_file_action.triggered.connect(self.run_file)
        open_file_action.setShortcut('Ctrl+O')

        # Add the action to a menu
        file_menu = self.menuBar().addMenu('File')
        file_menu.addAction(open_file_action)

        # Create a QTextEdit widget to display error output
        self.text_edit = QTextEdit(self)
        self.setCentralWidget(self.text_edit)

    def run_file(self):
        # Open a file dialog to choose a Python file
        file_name, _ = QFileDialog.getOpenFileName(self, 'Open Python File', '', 'Python Files (*.py)')
        if file_name:
            # Create a QProcess to run the Python program
            process = QProcess(self)
            process.setProgram('python')
            process.setArguments([file_name])
            process.readyReadStandardError.connect(self.read_error_output)

            # Start the process
            process.start()

    def read_error_output(self):
        # Read the error output from the QProcess
        data = self.sender().readAllStandardError().data().decode('utf-8')

        # Display the error output in the QTextEdit widget
        self.text_edit.insertPlainText(data)

if __name__ == '__main__':
    app = QApplication(sys.argv)
    window = MainWindow()
    window.show()
    sys.exit(app.exec_())

this program is very simple, it can run the selected python program and capture the standard errors like attribute or division by zero errors

  • 1
    I don't know what you did that first day, but `os.system()` will certainly **not** catch any exception from an *externally* run program. It can't, nor it should. The only exception it could raise is if you use the wrong arguments for it (for instance, if you use multiple arguments or the wrong argument type). Besides: if you want to run an external program, you should prefer the `subprocess` module or QProcess in Qt. If you're doing it take benefits or multiple cores, then use the `multiprocessing` module. – musicamante Feb 07 '23 at 01:00
  • it should did worked on that day in fact I was very happy with that solution, and after turning on and off and run the program again, it does not work anymore – Blas Lomibao Feb 07 '23 at 01:31
  • 1
    No, it didn't. You probably did something else or didn't watch carefully, because, as said, `os.system()` does **not** raise any exception if the program fails, not even if the program doesn't exist, and in fact the [documentation doesn't mention any of that](//docs.python.org/3/library/os.html#os.system), because **it couldn't**: similarly to `subprocess.run()` and similar functions, you can only get the exit status (which the convention of 0 if the program exited normally and other values for any failure), but can **not** "catch the exception". You may *eventually* get its stderr at most. – musicamante Feb 07 '23 at 01:46
  • 1
    It is physically impossible for a program to actually catch a python exception (and I mean the *actual* exception, not the output of stderr) of another instance of the interpreter *launched as a separate process*, because that exception is and can only be handled from *that* other interpreter process. It wouldn't even make sense: with `os.system()` (and, similarly, `subprocess` functions) you could run anything, such as *another python interpreter* that implements an exception that doesn't exist in the current one (how could it handle it?) or any kind of program that doesn't even use python. – musicamante Feb 07 '23 at 01:53
  • 1
    I've already marked this for closure with the "not reproducible" reason, but consider this as duplicate of [Python try block does not catch os.system exceptions](https://stackoverflow.com/q/12373563). – musicamante Feb 07 '23 at 01:55
  • Maybe this is just a typo, but in `Window_dev.initUI()` you are setting `self.worker` to an instance of the `WorkerThread` class, while the class below it is `WorkerThread1` – nigh_anxiety Feb 07 '23 at 02:09

1 Answers1

1

While I do not know what the script server.py is supposed to do, the general rule here is to use the subprocess package, intended to replace things like os.system in the near future.

For your case in hand, the following code throws if any error is found when running the command given (python3) with the given parameters (server.py):

import subprocess as sp                                                                                               
                                                                                                                      
def run():                                                                                                            
    try:                                                                                                              
        a = sp.run(["python3", "server.py"])                                                                          
        a.check_returncode()                                                                                          
    except sp.CalledProcessError as err:                                                                              
        raise err                                                                                                     
                                                                                                                      
run()
print("This line will not run!")

check_returncode() returns the exit code of the command run. If the code is nonzero (i.e. if an error occurred), such a function will throw a subprocess.CalledProcessError, which you can catch and raise if wanted.

Note that if you do not rise, the script will continue its normal course. Compare the above code with

import subprocess as sp                                                                                               
                                                                                                                      
def run():                                                                                                            
    try:                                                                                                              
        a = sp.run(["python3", "server.py"])                                                                          
        a.check_returncode()                                                                                          
    except sp.CalledProcessError as err:                                                                              
        print(err)                                                                                                     
                                                                                                                      
run()
print("This line will still run!")

JustLearning
  • 1,435
  • 1
  • 1
  • 9
  • Thank you for your answer, will try this option, will also work on another thread? – Blas Lomibao Feb 07 '23 at 04:03
  • @JohnCruze Don't ask if it'll work: try it. Then eventually ask for clarifications in case it doesn't. – musicamante Feb 07 '23 at 06:53
  • ohh I tried it on my actual project but it only returns this "Command '['python', 'server.py']' returned non-zero exit status 3221226505. " what I need is something like this: "Traceback (most recent call last): File "server.py", line 101, in run server.bind(('1.2.3.4', 505)) OSError: [WinError 10048] Only one usage of each socket address (protocol/network address/port) is normally permitted" Is there a way to catch that error? – Blas Lomibao Feb 07 '23 at 10:00
  • hello, the error can be captured by using Qprocess – Blas Lomibao Feb 16 '23 at 05:49