python-binance icon indicating copy to clipboard operation
python-binance copied to clipboard

Cannot create ThreadedWebsocketManager and Websocket API in the same thread

Open monkingxue opened this issue 1 year ago • 3 comments

Describe the bug I want to create a ThreadedWebsocketManager to subscribe to infomation updates and create a Client to place an order(client.ws_futures_create_order) via websocket api, but when I start the program reports an error This event loop is already running.

To Reproduce

from binance import ThreadedWebsocketManager, Client

api_key = ''
api_secret = ''

def main():

    symbol = 'BNBBTC'

    client = Client(api_key=api_key, api_secret=api_secret)
    twm = ThreadedWebsocketManager(api_key=api_key, api_secret=api_secret)
    twm.start()

    def handle_socket_message(msg):
        print(f"message type: {msg['e']}")
        # print(msg)

    twm.start_kline_socket(callback=handle_socket_message, symbol=symbol)

    account = client.ws_futures_v2_account_status()
    print(f"account: {account}")

    twm.join()

if __name__ == "__main__":
    main()

Expected behavior A clear and concise description of what you expected to happen.

Environment (please complete the following information):

  • Python version: 3.9
  • Virtual Env: pipenv
  • OS: Mac
  • python-binance 1.0.28

Logs Please set logging to debug and paste any logs here, or upload debug.log file to the issue.

Traceback (most recent call last):
  File "test.py", line 33, in <module>
    main()
  File "test.py", line 21, in main
    account = client.ws_futures_v2_account_status()
  File "/Users/.local/share/virtualenvs/datainfra-gsnu_lej/lib/python3.8/site-packages/binance/client.py", line 13286, in ws_futures_v2_account_status
    return self._ws_futures_api_request_sync("v2/account.status", True, params)
  File "/Users/.local/share/virtualenvs/datainfra-gsnu_lej/lib/python3.8/site-packages/binance/base_client.py", line 389, in _ws_futures_api_request_sync
    return self.loop.run_until_complete(
  File "/Users/.pyenv/versions/3.8.16/lib/python3.8/asyncio/base_events.py", line 592, in run_until_complete
    self._check_running()
  File "/Users/.pyenv/versions/3.8.16/lib/python3.8/asyncio/base_events.py", line 552, in _check_running
    raise RuntimeError('This event loop is already running')
RuntimeError: This event loop is already running

Additional context Add any other context about the problem here.

monkingxue avatar Apr 06 '25 08:04 monkingxue

Hi @monkingxue ,

Yes, this happens when trying to mixing synchronous and asynchronous code and this fails because the event loop is already running in the ThreadedWebsocketManager thread.

Can you try switching to use the asnycClient insead of the client?

This code is working for me

from binance import ThreadedWebsocketManager, AsyncClient
import asyncio

api_key = ''
api_secret = ''

async def run_websocket_operations():
    symbol = 'BNBBTC'
    
    # Create async client
    client = await AsyncClient.create(api_key=api_key, api_secret=api_secret)
    
    try:
        # Get account status using async call
        account = await client.ws_get_symbol_ticker(symbol=symbol)
        print(f"account: {account}")
    finally:
        await client.close_connection()

def handle_socket_message(msg):
    print(f"message type: {msg['e']}")
    # print(msg)

def main():
    # Start ThreadedWebsocketManager
    twm = ThreadedWebsocketManager(api_key=api_key, api_secret=api_secret)
    twm.start()

    # Start kline socket
    twm.start_kline_socket(callback=handle_socket_message, symbol='BNBBTC')

    # Run async operations in a separate event loop
    loop = asyncio.new_event_loop()
    asyncio.set_event_loop(loop)
    loop.run_until_complete(run_websocket_operations())
    
    twm.join()

if __name__ == "__main__":
    main()

pcriadoperez avatar Apr 06 '25 20:04 pcriadoperez

hi @pcriadoperez , thank you very much for your reply, I have run through the whole use case, but I found a new problem, the parameter type of websocket's order interface is not quite the same as restful. I use Decimal to express the number of orders, and I get the error: Object of type Decimal is not JSON serializable, which is not reported by the restful api.

monkingxue avatar Apr 07 '25 05:04 monkingxue

I want to create more than one ThreadWebsocketManager in the main thread, but I got the this event loop is already running, do I need to create different ThreadWebsocketManagers in the sub-thread?

monkingxue avatar Apr 09 '25 12:04 monkingxue