Elektordi / obs-websocket-py

Python library to communicate with an obs-websocket server (for OBS Studio)
MIT License
223 stars 59 forks source link

Handling error when OBS closes before script #75

Closed amorphousWaste closed 1 year ago

amorphousWaste commented 2 years ago

I have a script that maintains a persistent connection to OBS by calling ws.connect(), continuing to do whatever, and then calling ws.disconnect() on close. If OBS is closed before the script finishes, it crashes the script. Is there a way to handle losing the connection to OBS? It looks like the error is happening in another thread and I can't simply wrap it in a try-except. It also looks like there is already an exception handler in core.py that should handle this, but isn't.

This is the traceback:

Exception in thread Thread-2:
Traceback (most recent call last):
  File "/usr/local/lib/python3.9/site-packages/obswebsocket/core.py", line 226, in run
    message = self.ws.recv()
  File "/usr/local/lib/python3.9/site-packages/websocket/_core.py", line 362, in recv
    opcode, data = self.recv_data()
  File "/usr/local/lib/python3.9/site-packages/websocket/_core.py", line 385, in recv_data
    opcode, frame = self.recv_data_frame(control_frame)
  File "/usr/local/lib/python3.9/site-packages/websocket/_core.py", line 406, in recv_data_frame
    frame = self.recv_frame()
  File "/usr/local/lib/python3.9/site-packages/websocket/_core.py", line 445, in recv_frame
    return self.frame_buffer.recv_frame()
  File "/usr/local/lib/python3.9/site-packages/websocket/_abnf.py", line 341, in recv_frame
    self.recv_header()
  File "/usr/local/lib/python3.9/site-packages/websocket/_abnf.py", line 297, in recv_header
    header = self.recv_strict(2)
  File "/usr/local/lib/python3.9/site-packages/websocket/_abnf.py", line 376, in recv_strict
    bytes_ = self.recv(min(16384, shortage))
  File "/usr/local/lib/python3.9/site-packages/websocket/_core.py", line 529, in _recv
    return recv(self.sock, bufsize)
  File "/usr/local/lib/python3.9/site-packages/websocket/_socket.py", line 125, in recv
    raise WebSocketConnectionClosedException(
websocket._exceptions.WebSocketConnectionClosedException: Connection to remote host was lost.

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/usr/local/lib/python3.9/site-packages/obswebsocket/core.py", line 68, in connect
    self.ws.connect("ws://{}:{}".format(self.host, self.port))
  File "/usr/local/lib/python3.9/site-packages/websocket/_core.py", line 249, in connect
    self.sock, addrs = connect(url, self.sock_opt, proxy_info(**options),
  File "/usr/local/lib/python3.9/site-packages/websocket/_http.py", line 130, in connect
    sock = _open_socket(addrinfo_list, options.sockopt, options.timeout)
  File "/usr/local/lib/python3.9/site-packages/websocket/_http.py", line 206, in _open_socket
    raise err
  File "/usr/local/lib/python3.9/site-packages/websocket/_http.py", line 185, in _open_socket
    sock.connect(address)
ConnectionRefusedError: [Errno 61] Connection refused

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/usr/local/Cellar/python@3.9/3.9.10/Frameworks/Python.framework/Versions/3.9/lib/python3.9/threading.py", line 973, in _bootstrap_inner
    self.run()
  File "/usr/local/lib/python3.9/site-packages/obswebsocket/core.py", line 245, in run
    self.core.reconnect()
  File "/usr/local/lib/python3.9/site-packages/obswebsocket/core.py", line 86, in reconnect
    self.connect()
  File "/usr/local/lib/python3.9/site-packages/obswebsocket/core.py", line 73, in connect
    raise exceptions.ConnectionFailure(str(e))
obswebsocket.exceptions.ConnectionFailure: [Errno 61] Connection refused

Should I not be maintaining a persistent connection and using a reconnect, run command, disconnect pattern?

Any help would be greatly appreciated. Thank you.

adamoell commented 2 years ago

I am facing this exact issue, too, and would love to know what the way forward is. I can't really follow the connect/run command/disconnect pattern, as I need to handle scene change events from OBS. What would be really great would be if there was some sort of 'obs dropped the connection' (on_disconnect?) event that I could handle gracefully instead of the unhandled connection just blowing me away. Thanks!

Joonas144 commented 2 years ago

there is:

from obswebsocket import obsws, events

def on_exit(message):
    # your function here
    pass

ws = obsws("...", "...", "...")
ws.register(on_exit, events.Exiting)

What I would love to know, is how would one reconnect after such event? Calling ws.connect seems to cause ConnectionFailure

adamoell commented 2 years ago

on_exit doesn't get invoked - your script crashes :-(

Elektordi commented 1 year ago

Fixed on master. There is an example here: https://github.com/Elektordi/obs-websocket-py/blob/master/samples/reconnect.py