serhii.net

In the middle of the desert you can say anything you want

30 Sep 2021

Day 1003

Pycharm presentation mode and font size

Previously, I had to manually increase font sizes in Pycharm when presenting stuff in meeting, and couldn’t automate it.

Today I realized that I can change the script resolution to a lower one, giving the same results, and easily automatable through randr and a shell script!

Pycharm moving functions

“Right click -> Refactor” works not just for renaming files/folders, but also for moving functions to different files!

Miroboard moving

Holding <space> makes the mouse move the view, not the content

Logging in Python

logging — Logging facility for Python — Python 3.9.7 documentation

logger.exception() exists! Exception info is written as given by the exception handler.

Exceptions handling in Python

Was looking for a strategy to handle errors in a complex-ish applications, with logging, different levels etc.

  • Three options how to deal with exceptions:1

    • Swallow it quietly (handle it and keep running).
    • Do something like logging, but re-raise the same exception to let higher levels handle.
    • Raise a different exception instead of the original.
  • Defining your custom exception1

    class SuperError(Exception):
        def __init__(self, message):
            Exception.__init__(message)
            self.when = datetime.now()
    
    raise SuperError('Something went wrong')
    
  • Re-raising the same exception after handling it 1

    def invoke_function(func, *args, **kwargs):
        try:
            return func(*args, **kwargs)
        except Exception as e:
            print type(e)
            raise
    
  • Ways to clean stuff up in try..catch blocks:2

    • try: - execute this
    • except: execute this if there’s an exception
    • else: - execute if no exceptions
    • finally: - always run this code
  • Context managers

    • Alternative to finally, standard with ... syntax
  • Logging best practice1

    import logging
    logger = logging.getLogger()
    def f():
        try:
            flaky_func()
        except Exception:
            logger.exception()
            raise
    

    If you re-raise, make you sure you don’t log the same exception over and over again at different levels.1

    The simplest way to do it is to let all exceptions propagate (unless they can be handled confidently and swallowed earlier) and then do the logging close to the top level of your application/system.1

  • Error logger decorator for the above1

    def log_error(logger)
        def decorated(f):
            @functools.wraps(f)
            def wrapped(*args, **kwargs):
                try:
                    return f(*args, **kwargs)
                except Exception as e:
                    if logger:
                        logger.exception(e)
                    raise
            return wrapped
        return decorated
    

    And usage:

    import logging
    logger = logging.getLogger()
    
    @log_error(logger)
    def f():
        raise Exception('I am exceptional')
    
  • If there are multiple decorators, that one should be the immediate next one to the function! When I did it wrong, I got an exception (ha) about “‘staticmethod’ object is not callable”.

    The correct way is:

    @staticmethod
    @return_trainer_exception(logger=None)
    
Nel mezzo del deserto posso dire tutto quello che voglio.