Audible Errors - Custom non-blocking text-to-speech handler for Python logging module

I am building a faceless Raspberry Pi based long term art setup. A common use of Text-to-Speech on a raspberry pi is for people setting up their Pis to speak their IP address on boot to make SSHing easier.

I loved the logging module. Never again commenting on the countless claims of the press, my heart shines. For my situation, it would be ideal to have a registration handler that talks about the error. The StreamHandler and FileHandler that I am currently using are great for diagnosing development and post-issues, but terrible for solving problems in-place. Also, there is something adorable SciFi about my robot yelling bugs at me.

I found an example of a custom handler for SMS based error logging and tried to implement my own with e-talk. It says, but the whole program stops at the end of the first sentence spoken.

I'm looking for advice on how to implement a thread handler that doesn't block program execution. My broken custom handler:

import logging
import os

#based on SMSHandler http://pantburk.info/?blog=77

def speak(stringToSay):
    '''say whatver it is told to say, squleching annoying warnings'''
    stringToSay = "'"+stringToSay+"'"
#English female voice, emphasis on capitals (-k), speaking slowly (-s) using direct text:-
#the 2>/dev/null' is there because any calls to the rPi audio card result in a dozen warnings.
#  see: http://raspberrypi.stackexchange.com/questions/3412/errors-with-espeak
    os.system('espeak  -ven+f3 -k5 -s150 '+stringToSay+' 2>/dev/null')

class TALKHandler(logging.Handler): # Inherit from logging.Handler
        def __init__(self):
                # run the regular Handler __init__
                logging.Handler.__init__(self)
        def emit(self, record):
                # record.message is the log message
                speak(record.message)

      

An excerpt from the program that is being registered:

logging.handlers.TALKHandler = speechHandler.TALKHandler
# create the handler object
talkingHandler = logging.handlers.TALKHandler()
# Configure the handler to only send SMS for critical errors
talkingHandler.setLevel(logging.CRITICAL)
# and finally we add the handler to the logging object
logger.addHandler(talkingHandler)

ipAddress = [(s.connect(('8.8.8.8', 80)), s.getsockname()[0], s.close()) for s in [socket.socket(socket.AF_INET, socket.SOCK_DGRAM)]][0][1]
ipAddress = " ".join(ipAddress)
ipAddress = ipAddress.replace(".","dot")
logger.critical("Current IP Address is " + ipAddress  )

      

+3


source to share


1 answer


I know this was asked years ago - I missed it when it was published and stumbled upon it by accident. The following works for me:

import logging
import subprocess
import sys

class TalkHandler(logging.Handler):
    def emit(self, record):
        msg = self.format(record)
        cmd = ['espeak', '-ven+f3', '-s150', msg]
        p = subprocess.Popen(cmd, stdout=subprocess.PIPE,
                             stderr=subprocess.STDOUT)
        p.communicate()

def configure_logging():
    h = TalkHandler()
    root = logging.getLogger()
    root.addHandler(h)
    root.setLevel(logging.DEBUG)

def main():
    logging.info('Hello')
    logging.debug('Goodbye')

if __name__ == '__main__':
    configure_logging()
    sys.exit(main())

      



When I launch it, I hear "Hello" and then "Goodbye".

0


source







All Articles