I'm working on an addon that has a polling loop (using a timer modal) that needs to send a network request on every iteration (once a minute):
class PollingLoopOperator(bpy.types.Operator):
"""Polling loop"""
bl_idname = "wm.modal_polling_loop"
bl_label = "Polling Loop"
_timer = None
def modal(self, context, event):
if event.type == 'TIMER':
# Run network polling request
return {'PASS_THROUGH'}
def execute(self, context):
wm = context.window_manager
# Run every minute
self._timer = wm.event_timer_add(60, context.window)
wm.modal_handler_add(self)
return {'RUNNING_MODAL'}
At first I was thinking of just using the requests
library, but then I realized that wouldn't work because it's blocking, and sending a blocking network request every minute would be terrible from a UX perspective. I can't use another thread because Blender is not thread safe. So far I've thought of the fallowing possible solutions, but they don't seem that great:
- Use
multiprocessing
to run the request in another process, I could still use therequests
library, but it would have the added overhead of an additional process - Use
asyncio.open_connection
, seems like maybe the best solution so far - Keep a non blocking
socket
open and push data from the server, the polling loop just checks to see if the socket has any data. This is a pretty low level option and would require manual ssl handling and building a custom protocol. Plus, it would be harder to build the backend for. But it would have a few major benefits:- The polling loop could run much more frequently then 1 minute because all it would do is check to see if there is any data in the socket
- Less overhead because there is only a single socket connection opened
Which of these would be the best solution? Or, is there an even better solution I haven't thought of?