• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

Przechwytywanie błędów .exe w Pythonie

Mały hosting, OGROMNE możliwości
+1 głos
207 wizyt
pytanie zadane 24 maja 2024 w Python przez kacper1445 Mądrala (5,070 p.)

Hej, piszę program testujący aplikacje c++, na podstawie danych wejściowych i odpowiadających danych wyjściowych. Problem polega na tym że nie mogę w żaden sposób przechwycić błędów rzucanych przez plik .exe aplikacji C++.

Dla testów napisałem prosty kod w C++:

#include <iostream>

int main()
{
    throw std::out_of_range("");
}

Próbując uruchamiać testy za pomocą aplikacji w Pythonie, wyskakuje mi okno:

Chciałbym żeby tego typu okna nie wyświetlały się podczas testów i żebym wiedział jakie błędy wystąpiły podczas runtime aplikacji C++.

Kod w Pythonie który uruchamia .exe C++:

@staticmethod
    def __suppressWindowsErrorDialogs():
        SEM_FAILCRITICALERRORS: hex = 0x0001
        SEM_NOGPFAULTERRORBOX: hex = 0x0002
        SEM_NOALIGNMENTFAULTEXCEPT: hex = 0x0004
        SEM_NOOPENFILEERRORBOX: hex = 0x8000

        # SetErrorMode function suppresses system error dialogs
        ctypes.windll.kernel32.SetErrorMode(
            SEM_FAILCRITICALERRORS |
            SEM_NOGPFAULTERRORBOX |
            SEM_NOALIGNMENTFAULTEXCEPT |
            SEM_NOOPENFILEERRORBOX
        )

    def __getProgramOutput(self, data: str, timeout: float = 30) -> str | Tuple[int, str]:
        try:
            self.__suppressWindowsErrorDialogs()
            startupinfo = subprocess.STARTUPINFO()
            startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW
            creationflags = subprocess.CREATE_NO_WINDOW

            process: subprocess.Popen = subprocess.Popen([self.__exe_path],
                                                         stdout=subprocess.PIPE,
                                                         stderr=subprocess.PIPE,
                                                         stdin=subprocess.PIPE,
                                                         text=True,
                                                         startupinfo=startupinfo,
                                                         creationflags=creationflags)

            out: str
            err: str
            out, err = process.communicate(input=data, timeout=timeout)

            print(out)
            print(err)

        except PermissionError as e:
            return PERMISSION_DENIED, e.filename
        except subprocess.TimeoutExpired as e:
            return f'TIMEOUT {e}'
        except subprocess.CalledProcessError as e:
            return f'{e.returncode}, {e.output}'

        input()
        # return result.stdout

 

komentarz 25 maja 2024 przez Oscar Nałogowiec (29,360 p.)
To nie kompiluj aplikacji C++ w trybie Debug. To okienko jest wyświetlane przez samą aplikację w C++ - co prawda nie przez część napisaną przez autora, ale przez bibliotekę runtime. Teoretycznie można uruchamianej aplikacji podmienić biblioteki, ale to chyba przesada. Kazdy uruchomiony program zwraca do systemu tzw kod zakończenia (dla poprawnego wykonania przyjmuje się 0) - dlatego w C++ main może być int. Możesz w main zlapać wyjątki i zwrócić odpowiedni kod błędu - to okienko to kwestia niezłapanego wyjątku co powoduje zakończenie aplikacji.
komentarz 26 maja 2024 przez VBService Ekspert (256,580 p.)

Dokładnie, możesz np. przechwytywać wyjątki i wypisywać je na standardowe wyjście błędów. Nie piszę w c++, ale wydaję Mi się, że mogło by to wyglądać np. tak

#include <iostream>
#include <stdexcept>

int main() {
    try {
        throw std::out_of_range("Out of range error"); // Dodanie opisu błędu
    } catch (const std::exception &e) {
        std::cerr << "Exception caught: " << e.what() << std::endl;
        return 1; // Zwracanie kodu błędu
    }
    return 0;
}

w ten sposób będzie prawdopodobnie można je odczytać w python-ie po przez przechwytanie informacji ze standardowego wyjścia błędów.

 

 

 

BTW, dodałbym jeszcze tu ogólną obsługę wyjątków

        except PermissionError as e:
            return PERMISSION_DENIED, e.filename
        except subprocess.TimeoutExpired as e:
            return f'TIMEOUT {e}'
        except subprocess.CalledProcessError as e:
            return f'{e.returncode}, {e.output}'
        except Exception as e:  # Dodanie ogólnej obsługi wyjątków
            return f'Unexpected error: {str(e)}'

 

Zaloguj lub zarejestruj się, aby odpowiedzieć na to pytanie.

Podobne pytania

–3 głosów
5 odpowiedzi 14,454 wizyt
+2 głosów
0 odpowiedzi 594 wizyt
pytanie zadane 11 listopada 2024 w Python przez MichaelM Gaduła (3,000 p.)
+2 głosów
3 odpowiedzi 705 wizyt
pytanie zadane 24 maja 2024 w Python przez HUBSON2912 Obywatel (1,560 p.)

93,718 zapytań

142,629 odpowiedzi

323,261 komentarzy

63,265 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj

Twierdza Linux. Bezpieczeństwo dla dociekliwych

Aby uzyskać rabat -10%, użyjcie kodu pasja-linux, wpisując go w specjalne pole w koszyku.

...