debugging of a randomly crashing Livestream with EXE
-
Hi, im running a python EXE (made with cx_freeze). The program is sometimes randomly crashing. Because it's a exe i can't see any error messages. Is there a possibility how to make a error logging for a EXE file?
def cap_img(self, cap): ret, img = cap.read() img = cv2.flip(img,1)#flip cam img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB).copy() height, width, channel = img.shape step = channel * width # QImage::copy() img = QImage(img.data, width, height, step, QImage.Format_RGB888).copy() if height != HEIGHT and width != WIDTH: img = img.scaled(WIDTH, HEIGHT) return img def snap_img(self, cap): ret, img = cap.read() img = cv2.flip(img,1)#flip cam self.snap_cv = img.copy() img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) height, width, channel = img.shape step = channel * width self.snap = QImage(img.data, width, height, step, QImage.Format_RGB888).copy() if height != HEIGHT and width != WIDTH: self.snap = self.snap.scaled(WIDTH, HEIGHT) # Zeige Livestream def livestream_overlays(self): super().__init__() self.overlay_base() # Rote linien als overlays if self.state == 1 or self.state == 2: self.overlay_red() elif self.state == 3: self.overlay_blue() # Grüne linien als overlays (L-Taste) if self.lvalue: self.overlay_green() # Zeige Livestream mit Overlays if self.spsn == True: img = self.img.scaled(int(w/2), int(h)) self.img2 = self.img2.scaled(int(w/2), int(h)) if self.state_cams == True: self.show_cam(self.img2,2) self.show_cam(img,3) else: self.show_cam(self.img2,3) self.show_cam(img,2) else: img = self.img.scaled(w, h) self.show_cam(img,1) def insertShape(self, img1, lines, linewidth, color): img = img1.copy() painter = QPainter() pixmap = QPixmap(img) painter.begin(img) painter.setRenderHint(QPainter.Antialiasing) painter.drawPixmap(img.rect(), pixmap) painter.setPen(QPen(colors[color], linewidth)) for line in lines: painter.drawLine(line[0],line[1],line[2],line[3]) return img def overlay_base(self): if self.pop != None: if self.pop.chns != None: self.ns = self.pop.chns self.pop = None img = self.cap_img(self.cap).copy()
-
Hi,
Use the Python logging framework and add an output to a file.
-
This is a copy of my answer from here
Here are some good resources:
Briefly, (as far as I understand)
-
The logging module provides hierarchical loggers meaning if the root logger (the logger you get with
logging.getLogger()
) is formatted in a certain way all the loggers with other names, (logging.getLogger("other_logger")
) will be formatted the same (unless if you setpropagate
toFalse
) -
The best practice for big projects as explained in the links above will be to define a logger configuration at the beginning of your package (i.e in
__main__.py
) and then just calllogging.getLogger(__name__)
Example:
application:
src ├── animals │ ├── __init__.py │ ├── dog.py | |── cat.py | |── fish.py └── __main__.py
Inside main.py:
import logging from logging.config import dictConfig LOG_CONFIG = { 'version': 1, 'handlers': { 'console': { 'level': 'DEBUG', 'formatter': 'std', 'class': 'logging.StreamHandler', 'stream': 'ext://sys.stdout' }, 'detailed_console': { 'level': 'DEBUG', 'formatter': 'error', 'class': 'logging.StreamHandler', 'stream': 'ext://sys.stdout' }, 'std_fh': { 'level': 'INFO', 'formatter': 'std', 'class': 'logging.handlers.RotatingFileHandler', 'filename': 'logs/std.log', 'mode': 'a', 'maxBytes': 1048576, 'backupCount': 10 }, 'detailed_fh': { 'level': 'WARNING', 'formatter': 'error', 'class': 'logging.handlers.RotatingFileHandler', 'filename': 'logs/errors.log', 'mode': 'a', 'maxBytes': 1048576, 'backupCount': 10 } }, 'loggers': { '': { # root logger 'level':'NOTSET', 'handlers': ['std_fh', 'console'], }, 'D.src': { 'propagate': False, 'handlers': ['detailed_fh','detailed_console'], }, 'src': { 'propagate': False, 'handlers': ['std_fh','console'], } }, 'formatters': { 'std': { 'format': '[%(levelname)s - %(asctime)s - %(name)s::] %(message)s' }, 'error': { 'format': '[%(levelname)s - %(asctime)s - %(name)s - %(process)d::module :%(module)s|Line: %(lineno)s] messages:[ %(message)s ]' }, } } logging.config.dictConfig(LOG_CONFIG) rootL = logging.getLogger() # this is a root logger srcL = logging.getLogger(__name__) # this is an `src` logger detL = logging.getLogger("D.") # this is 'detailed' def main(): rootL.debug("hello from rootL") srcL.debug("hello from srcL") detL.debug("hello from detL")
Now, let's see how they print from main.py
>>> python -m src >>> [DEBUG - 2022-01-28 04:09:14,137 - root::] hello from rootL >>> [DEBUG - 2022-01-28 04:09:14,137 - __main__::] hello from srcL >>> [DEBUG - 2022-01-28 04:20:45,153 - D.src - 36742::module :__main__|Line: 83] messages:[ hello from detL ]
Now in cat.py, you do the same except you don't need to config it again.
import logging rootL = logging.getLogger() # this is a root logger srcL = logging.getLogger(__name__) # this is an `src` logger detL = logging.getLogger("D."+__name__) # this is 'detailed' rootL.debug("hello from rootL") srcL.debug("hello from srcL") detL.debug("hello from detL")
and I would recommend using the
dict
config instead of a file config for security measures (search here foreval()
). -
-
Then you need to start your application through a debugger to try to get more information about what is happening.