Socket.IO Client Library in Python [closed]
Asked Answered
D

6

49

Can anyone recommend a Socket.IO client library for Python? I've had a look around, but the only ones I can find are either server implementations, or depend on a framework such as Twisted.

I need a client library that has no dependencies on other frameworks.

Simply using one of the many connection types isn't sufficient, as the python client will need to work with multiple socketio servers, many of which won't support websockets, for example.

Dispread answered 21/1, 2011 at 17:53 Comment(0)
S
43

Archie1986's answer was good but has become outdated with socketio updates (more specifically, its protocol : https://github.com/LearnBoost/socket.io-spec)... as far as i can tell, you need to perform the handshake manually before you can ask for a transport (e.g., websockets) connection... note that the code below is incomplete and insecure... for one, it ignores the list of supported transports returned in the handshake response and always tries to get a websocket... also it assumes that the handshake always succeeds... nevertheless, it's a good place to start

import websocket, httplib

...

'''
    connect to the socketio server

    1. perform the HTTP handshake
    2. open a websocket connection '''
def connect(self) :
    conn  = httplib.HTTPConnection('localhost:8124')
    conn.request('POST','/socket.io/1/')
    resp  = conn.getresponse() 
    hskey = resp.read().split(':')[0]

    self._ws = websocket.WebSocket(
                    'ws://localhost:8124/socket.io/1/websocket/'+hskey,
                    onopen   = self._onopen,
                    onmessage = self._onmessage)

....

you might also want to read up on python-websockets: https://github.com/mtah/python-websocket

Shulins answered 28/9, 2011 at 16:17 Comment(2)
This works great for me. Thanks so much for the updated answer! I wish the OP would re-promote this one, because the actual answer (as you point out) is not going to actually work with the current spec. I filled out the rest of the code for a simple command line tool that works nicely. It might be useful to someone else: gist.github.com/1402238 It's basically just your code with some very minor other stuff that's mostly obvious, but I hope it'll save someone some time.Murat
any updates on this answer as of 2019?Limiting
M
25

First of all, I'm not sure why some of your Socket.IO servers won't support websockets...the intent of Socket.IO is to make front-end browser development of web apps easier by providing an abstracted interface to real-time data streams being served up by the Socket.IO server. Perhaps Socket.IO is not what you should be using for your application? That aside, let me try to answer your question...

At this point in time, there aren't any Socket.IO client libraries for Python (gevent-socketio is not a Socket.IO client library for Python...it is a Socket.IO server library for Python). For now, you are going to have to piece some original code together in order to interface with Socket.IO directly as a client while accepting various connection types.

I know you are looking for a cure-all that works across various connection types (WebSocket, long-polling, etc.), but since a library such as this does not exist as of yet, I can at least give you some guidance on using the WebSocket connection type based on my experience.

For the WebSocket connection type, create a WebSocket client in Python. From the command line install this Python WebSocket Client package here with pip so that it is on your python path like so:

pip install -e git+https://github.com/liris/websocket-client.git#egg=websocket

Once you've done that try the following, replacing SOCKET_IO_HOST and SOCKET_IO_PORT with the appropriate location of your Socket.IO server:

import websocket

SOCKET_IO_HOST = "127.0.0.1"
SOCKET_IO_PORT = 8080

socket_io_url = 'ws://' + SOCKET_IO_HOST + ':' + str(SOCKET_IO_PORT) + '/socket.io/websocket'

ws = websocket.create_connection(socket_io_url)

At this point you have a medium of interfacing with a Socket.IO server directly from Python. To send messages to the Socket.IO server simply send a message through this WebSocket connection. In order for the Socket.IO server to properly interpret incoming messages through this WebSocket from your Python Socket.IO client, you need to adhere to the Socket.IO protocol and encode any strings or dictionaries you might send through the WebSocket connection. For example, after you've accomplished everything above do the following:

def encode_for_socketio(message):
    """
    Encode 'message' string or dictionary to be able
    to be transported via a Python WebSocket client to 
    a Socket.IO server (which is capable of receiving 
    WebSocket communications). This method taken from 
    gevent-socketio.
    """
    MSG_FRAME = "~m~"
    HEARTBEAT_FRAME = "~h~"
    JSON_FRAME = "~j~"

    if isinstance(message, basestring):
            encoded_msg = message
    elif isinstance(message, (object, dict)):
            return encode_for_socketio(JSON_FRAME + json.dumps(message))
    else:
            raise ValueError("Can't encode message.")

    return MSG_FRAME + str(len(encoded_msg)) + MSG_FRAME + encoded_msg

msg = "Hello, world!"
msg = encode_for_socketio(msg)
ws.send(msg)
Mask answered 31/5, 2011 at 21:3 Comment(1)
full example: pastebin.com/1Xt6X4K5 - but I'm not really using HTTP exactly, I had to modify websocket.py like this: pastebin.com/rh9WxxJA because, I suspect my version of urlparse doesn't recognise 'ws://' web socket protocol.Judenberg
P
22

The socketIO-client library supports event callbacks and channels thanks to the work of contributors and is available on PyPI under the MIT license.

Emit with callback.

from socketIO_client import SocketIO

def on_bbb_response(*args):
    print 'on_bbb_response', args

with SocketIO('localhost', 8000) as socketIO:
    socketIO.emit('bbb', {'xxx': 'yyy'}, on_bbb_response)
    socketIO.wait_for_callbacks(seconds=1)

Define events.

from socketIO_client import SocketIO

def on_aaa_response(*args):
    print 'on_aaa_response', args

socketIO = SocketIO('localhost', 8000)
socketIO.on('aaa_response', on_aaa_response)
socketIO.emit('aaa')
socketIO.wait(seconds=1)

Define events in a namespace.

from socketIO_client import SocketIO, BaseNamespace

class Namespace(BaseNamespace):

    def on_aaa_response(self, *args):
        print 'on_aaa_response', args
        self.emit('bbb')

socketIO = SocketIO('localhost', 8000)
socketIO.define(Namespace)
socketIO.emit('aaa')
socketIO.wait(seconds=1)

Define different namespaces on a single socket.

from socketIO_client import SocketIO, BaseNamespace

class ChatNamespace(BaseNamespace):

    def on_aaa_response(self, *args):
        print 'on_aaa_response', args

class NewsNamespace(BaseNamespace):

    def on_aaa_response(self, *args):
        print 'on_aaa_response', args

socketIO = SocketIO('localhost', 8000)
chatNamespace = socketIO.define(ChatNamespace, '/chat')
newsNamespace = socketIO.define(NewsNamespace, '/news')

chatNamespace.emit('aaa')
newsNamespace.emit('aaa')
socketIO.wait(seconds=1)
Propagable answered 9/8, 2012 at 12:35 Comment(7)
Heh, we've come full circle, seeing as the socketIO-client package was spawned from the related SO question: #6693408Raskin
i am getting the warning WARNING:root:localhost:8000/socket.io [waiting for connection] ('Connection aborted.', error(111, 'Connection refused'))...can you help?Eire
Is your socket.io server running? Which version of the socket.io server are you using?Propagable
Only one event is working socketIO.on('aaa_response', on_aaa_response). If I am adding multiple events only first one is working??Shilohshim
Uh-oh that's not good. Could you please post an issue on the github repository with some sample code so that we can reproduce your situation?Propagable
@Wazzzy Do your multiple events have different names or are you trying to attach multiple callbacks to 'aaa_response'? Currently (as of 0.7.2), there can only be one callback per event.Propagable
Hi, I am also meet [socket.io waiting for connection], so which exception should I handle here, and add time.sleep for a while then retry?Disjunction
J
5

The SocketTornad.IO library with the popular asynchronous Tornado Web Server is also one of the options available for python.

Jaworski answered 27/2, 2012 at 14:15 Comment(1)
or even better, the more current version of Tornadio2: github.com/mrjoes/tornadIO2 --- but these are server libs, not intended for use as a client.Weasner
S
4

Wrote one: https://github.com/amitu/amitu-websocket-client/blob/master/amitu/socketio_client.py. It only supports websockets so it may have only marginal utility for you.

Scandalmonger answered 17/12, 2011 at 17:36 Comment(3)
when executing the run() method i get an error: Invalid frame - what could that mean?Weasner
Alp, it means there is a bug in the library. I have updated it based on pulls from various contributors. Please feel free to check the latest version and see if it helps.Scandalmonger
Thanks for your reply. In the meantime i switched to sockjs, which works like a charm. See #10950865Weasner
S
2

Did you have a look at gevent-socketio?

Hope it helps.

Sail answered 21/3, 2011 at 23:48 Comment(1)
gevent-socketio is not a Socket.IO client library for Python...it is a Socket.IO server library for PythonMask

© 2022 - 2024 — McMap. All rights reserved.