Giter VIP home page Giter VIP logo

python-signalr-client's Introduction

python-signalr-client

Python signalR client using asyncio. It's mainly based on TargetProcess signalR client which uses gevent.

I am mainly developing the client for my Python Bittrex Websocket project, however I would make it as universal as possible.

Road map

  • Error handling

Notices

None right now.

Performance and supplemental libraries

  • For better performance users can install uvloop and ujson which are automatically detected.
  • Users can pass a custom session to the client, i.e a cfscrape session in order to bypass Cloudflare.

Compatibility

Asyncio requires Python 3.5+.

For Python2.X compatibility try TargetProcess' gevent based SignalR client.

Installation

Pypi (most stable)

pip install signalr-client-aio

Github (master)

pip install git+https://github.com/slazarov/python-signalr-client.git

Github (work in progress branch)

pip install git+https://github.com/slazarov/python-signalr-client.git@next-version-number

Sample usage

from signalr_aio import Connection
from base64 import b64decode
from zlib import decompress, MAX_WBITS
import json

def process_message(message):
    deflated_msg = decompress(b64decode(message), -MAX_WBITS)
    return json.loads(deflated_msg.decode())

# Create debug message handler.
async def on_debug(**msg):
    # In case of 'queryExchangeState'
    if 'R' in msg and type(msg['R']) is not bool:
        decoded_msg = process_message(msg['R'])
        print(decoded_msg)

# Create error handler
async def on_error(msg):
    print(msg)


# Create hub message handler
async def on_message(msg):
    decoded_msg = process_message(msg[0])
    print(decoded_msg)

if __name__ == "__main__":
    # Create connection
    # Users can optionally pass a session object to the client, e.g a cfscrape session to bypass cloudflare.
    connection = Connection('https://beta.bittrex.com/signalr', session=None)

    # Register hub
    hub = connection.register_hub('c2')

    # Assign debug message handler. It streams unfiltered data, uncomment it to test.
    connection.received += on_debug

    # Assign error handler
    connection.error += on_error

    # Assign hub message handler
    hub.client.on('uE', on_message)
    hub.client.on('uS', on_message)

    # Send a message
    hub.server.invoke('SubscribeToExchangeDeltas', 'BTC-ETH')
    hub.server.invoke('SubscribeToSummaryDeltas')
    hub.server.invoke('queryExchangeState', 'BTC-NEO')

    # Start the client
    connection.start()

Change log

0.0.1.6.2 - 16/04/2018:

    • Removed uvloop as a requirement. However, it will be detected and utilized if installed.

0.0.1.5 - 06/04/2018:

  • Removed cfscrape from package. Users can optionally pass a cfscrape session to clients.
  • Removed ujson. The package will automatically detect if the user chooses to use ujson.

0.0.1.0 - Initial release.

Other libraries

Python Bittrex Websocket

Python websocket client for getting live streaming data from Bittrex Exchange.

Python Bittrex Autosell

Python CLI tool to auto sell coins on Bittrex.

It is used in the cases when you want to auto sell a specific coin for another, but there is no direct market, so you have to use an intermediate market.

python-signalr-client's People

Contributors

paulfjacobs avatar slazarov avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

python-signalr-client's Issues

A new release with support for Python 3.10

Hi @slazarov!

First of thank you for this great library. It's really helpful.

I've experimented a little to get the project ready for Python 3.10 in order to use it for (Fast-F1)[https://github.com/theOehrly/Fast-F1]. It seems like it could be pretty straight forward: oscr@45edbc4

How would you feel about making a new release with Python 3.10 support?

EDIT: I can make a pr for it just to be clear.

websockets.exceptions.ConnectionClosed: WebSocket connection is closed: code = 1006 (connection closed abnormally [internal]), no reason

16:15:23 24-02-2019, CRITICAL [bittrex.py:bittrex:run_blocking:135] Traceback (most recent call last):
File "/usr/local/lib/python3.7/site-packages/websockets/protocol.py", line 674, in transfer_data
message = yield from self.read_message()
File "/usr/local/lib/python3.7/site-packages/websockets/protocol.py", line 742, in read_message
frame = yield from self.read_data_frame(max_size=self.max_size)
File "/usr/local/lib/python3.7/site-packages/websockets/protocol.py", line 815, in read_data_frame
frame = yield from self.read_frame(max_size)
File "/usr/local/lib/python3.7/site-packages/websockets/protocol.py", line 884, in read_frame
extensions=self.extensions,
File "/usr/local/lib/python3.7/site-packages/websockets/framing.py", line 99, in read
data = yield from reader(2)
File "/usr/local/lib/python3.7/asyncio/streams.py", line 679, in readexactly
await self._wait_for_data('readexactly')
File "/usr/local/lib/python3.7/asyncio/streams.py", line 473, in _wait_for_data
await self._waiter
concurrent.futures._base.CancelledError

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
File "/code/data_api/bittrex.py", line 133, in run_blocking
self.run()
File "/code/data_api/bittrex.py", line 128, in run
connection.start()
File "/usr/local/lib/python3.7/site-packages/signalr_aio/_connection.py", line 36, in start
self.__transport.start()
File "/usr/local/lib/python3.7/site-packages/signalr_aio/transports/_transport.py", line 47, in start
self.ws_loop.run_until_complete(self.socket(self.ws_loop))
File "/usr/local/lib/python3.7/asyncio/base_events.py", line 584, in run_until_complete
return future.result()
File "/usr/local/lib/python3.7/site-packages/signalr_aio/transports/_transport.py", line 61, in socket
await self.handler(self.ws)
File "/usr/local/lib/python3.7/site-packages/signalr_aio/transports/_transport.py", line 70, in handler
loop=self.ws_loop, return_exceptions=False)
File "/usr/local/lib/python3.7/site-packages/signalr_aio/transports/_transport.py", line 77, in consumer_handler
message = await ws.recv()
File "/usr/local/lib/python3.7/site-packages/websockets/protocol.py", line 434, in recv
yield from self.ensure_open()
File "/usr/local/lib/python3.7/site-packages/websockets/protocol.py", line 658, in ensure_open
) from self.transfer_data_exc
websockets.exceptions.ConnectionClosed: WebSocket connection is closed: code = 1006 (connection closed abnormally [internal]), no reason

send query string

Hi

I want to send token as query string to authenticate?

How Do I do???

Fail to Install, please help

pip install signalr-client-aio
Collecting signalr-client-aio
Using cached https://files.pythonhosted.org/packages/83/90/82d1e2feffb173ad9d9c9e25f395eabec11c3426b5cb134a689227222d5d/signalr_client_aio-0.0.1.6.2-py2.py3-none-any.whl
Requirement already satisfied: requests>=2.18.4 in c:\users\terminal-3\anaconda3\lib\site-packages (from signalr-client-aio) (2.21.0)
Collecting websockets>=4.0.1 (from signalr-client-aio)
Using cached https://files.pythonhosted.org/packages/9c/60/f96f535f3354cb6ba5e5c7ab128b1c4802a2d040ee7225e3fe51242816c1/websockets-8.0.2-cp37-cp37m-win_amd64.whl
Requirement already satisfied: certifi>=2017.4.17 in c:\users\terminal-3\anaconda3\lib\site-packages (from requests>=2.18.4->signalr-client-aio) (2018.11.29)
Requirement already satisfied: idna<2.9,>=2.5 in c:\users\terminal-3\anaconda3\lib\site-packages (from requests>=2.18.4->signalr-client-aio) (2.8)
Requirement already satisfied: urllib3<1.25,>=1.21.1 in c:\users\terminal-3\anaconda3\lib\site-packages (from requests>=2.18.4->signalr-client-aio) (1.24.1)
Requirement already satisfied: chardet<3.1.0,>=3.0.2 in c:\users\terminal-3\anaconda3\lib\site-packages (from requests>=2.18.4->signalr-client-aio) (3.0.4)
Could not install packages due to an EnvironmentError: [Errno 2] No such file or directory: 'c:\users\terminal-3\anaconda3\lib\site-packages\pandas-0.24.2.dist-info\METADATA'

python 3.4?

Hi, thank you very much for this. I don't like the "wait" thing with the other signalR module, so I think async is a nice solution.
Unfortunately I still use python 3.4 and don't want to update.

So can I simply replace:

  1. "async def..." with
    "@asyncio.coroutine
    def ..."

  2. "await" with "yield from"

  3. "async with session.get(url) as r:" with "r = yield from session.get(url)"

and everything is fine? Or is it more complex?

edit:
Just saw you also use "async for".. I found no short alternative for this, just a big block of code in last example of response here: https://stackoverflow.com/questions/34338518/async-for-in-python-3-4

Error when connecting to Asp.net SignalR

I am trying your library with python 3.6.5
However, when I try to connect to my vendor signalr endpoint, I got the following error:

File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/signalr_aio/_connection.py", line 36, in start
self.__transport.start()
File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/signalr_aio/transports/_transport.py", line 47, in start
self.ws_loop.run_until_complete(self.socket(self.ws_loop))
File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/asyncio/base_events.py", line 468, in run_until_complete
return future.result()
File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/signalr_aio/transports/_transport.py", line 59, in socket
loop=loop) as self.ws:
File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/websockets/py35/client.py", line 2, in aenter
return await self
File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/websockets/py35/client.py", line 19, in await_impl
extra_headers=protocol.extra_headers,
File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/websockets/client.py", line 263, in handshake
raise InvalidStatusCode(status_code)
websockets.exceptions.InvalidStatusCode: Status code not 101: 400

Can you help me with this issue?

I have tried with this library https://github.com/TargetProcess/signalr-client-py and it is able to connect sucessfully. However, the project doesn't seem active recently, so i wanna try different available packages.

Python 3.10 incompatible

I'm trying to run the sample code from bittrex, which uses your library:
https://bittrex.github.io/api/v3#topic-Example-Socket-Clients

But I get this error:
TypeError: As of 3.10, the loop parameter was removed from Queue() since it is no longer necessary

traceback:
Traceback (most recent call last):
File "...\V3WebsocketExample.py", line 127, in
asyncio.run(main())
File "...\Python310\lib\asyncio\runners.py", line 44, in run
return loop.run_until_complete(main)
File "...\Python310\lib\asyncio\base_events.py", line 646, in run_until_complete
return future.result()
File "...\V3WebsocketExample.py", line 32, in main
await connect()
File "...\V3WebsocketExample.py", line 43, in connect
connection = Connection(URL)
File "...\Python310\lib\site-packages\signalr_aio_connection.py", line 24, in init
self.__transport = Transport(self)
File "...\Python310\lib\site-packages\signalr_aio\transports_transport.py", line 34, in init
self._set_loop()
File "...\Python310\lib\site-packages\signalr_aio\transports_transport.py", line 42, in _set_loop
self.invoke_queue = asyncio.Queue(loop=self.ws_loop)
File "...\Python310\lib\asyncio\queues.py", line 34, in init
super().init(loop=loop)
File "...\Python310\lib\asyncio\mixins.py", line 17, in init
raise TypeError(
TypeError: As of 3.10, the loop parameter was removed from Queue() since it is no longer necessary

Cryptopia websocket error

My problem is that I'm unable to use the library with Cryptopia's websocket.
Cryptopia's websocket is a totally undocumented, non-public websocket.
It also uses signalR. The endpoint url is www.cryptopia.co.nz/signalr and the hub is called 'notificationHub'.

I just tried to modify the example code:

from base64 import b64decode
from zlib import decompress, MAX_WBITS
import json


async def process_message(message):
    deflated_msg = decompress(b64decode(message), -MAX_WBITS)
    return json.loads(deflated_msg.decode())


# Create debug message handler.
async def on_debug(**msg):
    # In case of 'queryExchangeState'
    if 'R' in msg and type(msg['R']) is not bool:
        decoded_msg = await process_message(msg['R'])
        print(decoded_msg)


# Create error handler
async def on_error(msg):
    print(msg)


# Create hub message handler
async def on_message(msg):
    decoded_msg = await process_message(msg[0])
    print(decoded_msg)


if __name__ == "__main__":
    # Create connection
    # Users can optionally pass a session object to the client, e.g a cfscrape session to bypass cloudflare.
    connection = Connection('https://www.cryptopia.co.nz/signalr', session=None)

    # Register hub
    hub = connection.register_hub('notificationHub')

    # Assign debug message handler. It streams unfiltered data, uncomment it to test.
    connection.received += on_debug

    # Assign error handler
    connection.error += on_error

    # Assign hub message handler
    hub.client.on('uE', on_message)
    hub.client.on('uS', on_message)

    # Send a message
    hub.server.invoke('setTradePairSubscription', 1, 2)

    # Start the client
    connection.start()

But I always get the following error:

File "some_path\signalr_aio\hubs_hub.py", line 43, in handle

await self.__handlers[method](message)
KeyError: 'SendTradeDataUpdate'

What's the problem?

Add timeout between messages

My connection sometime stops receiving messages and would be nice to be able to raise an exception when there hasn't been a message so that you can do something about it. Or is there another way of doing this?

Websocket error handling

My websocket connection towards the signalr endpoint seems to drop every now and then, is there any way to capture this exception and reconnect? My lack of Python-fu is sever.

    message = await ws.recv()
  File "/srv/code/lib/python3.6/site-packages/websockets/protocol.py", line 350, in recv
    yield from self.ensure_open()
  File "/srv/code/lib/python3.6/site-packages/websockets/protocol.py", line 501, in ensure_open
    self.close_code, self.close_reason) from self.transfer_data_exc
websockets.exceptions.ConnectionClosed: WebSocket connection is closed: code = 1006 (connection closed abnormally [internal]), no reason

I'm using the following code:

            try:
                connection = Connection(self._stream, session=session)
                hub = connection.register_hub('myHub')
                connection.received += self.on_signalr_debug
                connection.error += self.on_signalr_error
                hub.client.on('NewStuff', self.on_signalr_stuff)
                connection.start()
                hub.server.invoke('authenticate', login, token)
                hub.server.invoke('coolStuff', mystuff)
            except Exception as err:
                _LOGGER.exception("Exception (%s) from SignalR", str(err))

But the Exception is never triggered? Because everything runs in asyncio in eventloop?

SignalR Core support?

Hi!
As far as I understand this does NOT support SignalR Core. Could anyone confirm it?

Example not working

Hi,
I wanted to try out the library, but it's not working for me. I copy pasted your example code under sample usage. I'm using the 0.0.1.5 version from PyPi.

Traceback (most recent call last):
  File "/home/meister245/virtualenv/py3_virtual/lib/python3.5/site-packages/signalr_aio/transports/_transport.py", line 67, in consumer_handler
    async for message in ws:
TypeError: 'async for' requires an object with __aiter__ method, got WebSocketClientProtocol

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "bittrex.py", line 51, in <module>
    connection.start()
  File "/home/meister245/virtualenv/py3_virtual/lib/python3.5/site-packages/signalr_aio/_connection.py", line 36, in start
    self.__transport.start()
  File "/home/meister245/virtualenv/py3_virtual/lib/python3.5/site-packages/signalr_aio/transports/_transport.py", line 39, in start
    self.ws_loop.run_until_complete(self.socket(self.ws_loop))
  File "uvloop/loop.pyx", line 1364, in uvloop.loop.Loop.run_until_complete
  File "/usr/lib/python3.5/asyncio/futures.py", line 274, in result
    raise self._exception
  File "/usr/lib/python3.5/asyncio/tasks.py", line 239, in _step
    result = coro.send(None)
  File "/home/meister245/virtualenv/py3_virtual/lib/python3.5/site-packages/signalr_aio/transports/_transport.py", line 53, in socket
    await self.handler(ws)
  File "/home/meister245/virtualenv/py3_virtual/lib/python3.5/site-packages/signalr_aio/transports/_transport.py", line 60, in handler
    loop=self.ws_loop, return_exceptions=False)
  File "/usr/lib/python3.5/asyncio/futures.py", line 361, in __iter__
    yield self  # This tells Task to wait for completion.
  File "/usr/lib/python3.5/asyncio/tasks.py", line 296, in _wakeup
    future.result()
  File "/usr/lib/python3.5/asyncio/futures.py", line 274, in result
    raise self._exception
  File "/usr/lib/python3.5/asyncio/tasks.py", line 239, in _step
    result = coro.send(None)
  File "/home/meister245/virtualenv/py3_virtual/lib/python3.5/site-packages/signalr_aio/transports/_transport.py", line 72, in consumer_handler
    raise Exception
Exception
Task was destroyed but it is pending!
task: <Task pending coro=<Transport.producer_handler() running at /home/meister245/virtualenv/py3_virtual/lib/python3.5/site-packages/signalr_aio/transports/_transport.py:77> wait_for=<Future pending cb=[Task._wakeup()]> cb=[gather.<locals>._done_callback(1)() at /usr/lib/python3.5/asyncio/tasks.py:637]>

done pending?

hi at transport.py line 69

wechatimg6

I am new about asyncio,I don't know why asyncio.gather will return a done and pending fs. done and pending fs return by call asyncio.wait function at python documention

wechatimg7

Error: There was an error invoking Hub method 'c2.QuerySummaryState'

Hi Stanislav,

I'm trying your signalr-client-aio and it is working perfectly for the given methods:

  • SubscribeToExchangeDeltas
  • SubscribeToSummaryDeltas
  • queryExchangeState

Though when I'm trying to invoke two other requests, i.e.:

hub.server.invoke('querySummaryState', 'BTC-ETH')
hub.server.invoke('SubscribeToSummaryLiteDeltas', 'BTC-ETH')

i get the following error messages:

  • There was an error invoking Hub method 'c2.querySummaryState'
  • There was an error invoking Hub method 'c2.SubscribeToSummaryLiteDeltas'

A bit of googling around showed that this could sign something going wrong at Bittrex server side. Therefore: Does this occur to others as well?
Or does the client not feature these methods?

I'm running Python 3.7 in a Jupyter Notebook environment.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.