I am using the following Python3 code to receive a text message from a xmpp server and then send that message to an Apple Messages user. The code runs on a machine running MacOS Monterey (12.6.7):
#! /usr/bin/python3
# xmpppy library must be installed using pip install xmpppy
# or import xmpp will not work
import xmpp
import subprocess
import sys
# Create a new XMPP client
client = xmpp.Client('xmpp.servername', debug=[])
# Connect to the XMPP server
client.connect()
# Authenticate the client
client.auth('xmppusername', 'xmpppassword')
# Send presence to indicate availability
client.sendInitPresence()
# Receive XMPP messages
def receive_message(conn, msg):
# Place the received message in a variable
received_message = msg.getBody()
cmdTemplate = '''
tell application "Messages"
send "{0}" to buddy "applemessagesuser@icloud.com" of service 1
end tell
'''
cmd = cmdTemplate.format(received_message)
subprocess.run(['osascript', '-e', cmd], capture_output=False)
# Register the message event handler
client.RegisterHandler('message', receive_message)
# Keep the connection alive to receive messages
while True:
client.Process(1)
# Disconnect from the XMPP server
client.disconnect()
The code runs great as long as the XMPP server is up and can be connected to, and in theory it should never exit, it should just keep listening for new messages from the XMPP server. The problem is that if the XMPP server has to be rebooted, or the internet connection goes down or something else interrupts the connection, the Python script quits with error messages similar to these:
File "./xmppreceive.py", line 40, in <module> client.Process(1) File "/Users/user/Library/Python/3.8/lib/python/site-packages/xmpp/dispatcher.py", line 129, in Process
raise ex
File "/Users/user/Library/Python/3.8/lib/python/site-packages/xmpp/dispatcher.py", line 307, in dispatch
handler['func'](session,stanza)
File "/Users/user/Library/Python/3.8/lib/python/site-packages/xmpp/dispatcher.py", line 219, in streamErrorHandler
raise exc((name,text))
xmpp.protocol.SystemShutdown: ('system-shutdown', 'Received SIGTERM')
Rather than fail completely, what I would like to see happen if the connection is lost is for the script to wait for it to come back up and then reconnect automatically. For example, wait ten seconds and retry the connection, and keep doing that until there server once again becomes available. But I can’t seem to figure out how to do that. I tried a couple of approaches I found online but they either errored out immediately (the program would not run at all) or the problem remained - if the server connection is lost the program just quits.
An inelegant solution is to run the Python script from a bash shell script and if the Python script exits, the bash script executes a “sleep 10” statement and then loops back and tries to launch the Python script again. But it seems kind of silly to have to do that - isn’t there some way to tell that the script has encountered an error condition and handle that within the Python script itself? Back in the days of BASIC (long, long ago) we could surround the potentially offending statement(s) with “ON ERROR GOTO …” statements; does Python have any similar error trapping capabilities, or is there a better way to handle this? It seems that the statement “client.Process(1)” is the point of failure here.