LUCIT-Systems-and-Development / unicorn-binance-websocket-api

A Python SDK by LUCIT to use the Binance Websocket API`s (com+testnet, com-margin+testnet, com-isolated_margin+testnet, com-futures+testnet, com-coin_futures, us, tr, dex/chain+testnet) in a simple, fast, flexible, robust and fully-featured way.
https://unicorn-binance-websocket-api.docs.lucit.tech/
Other
678 stars 166 forks source link

make sys.exit() calls in BinanceWebSocketApiSocket optional #156

Closed tropo84 closed 3 years ago

tropo84 commented 3 years ago

Hi there, first of all, great project! Thanks for all the work you are putting in to this!

I'd like to request to put all the calls to sys.exit() in BinanceWebSocketApiSocket behind some flag or something, so that the user can decide what happens. Or is there any important reason that i don't see why sys.exit() needs to be called? Is it related to threading or asyncio? Because in my opinion it would be much nicer to just raise any exception to the user code, so that the user has a chance to handle it. Also it seems very impractical to me that the interpreter is killed with sys.exit(0) simply when a stream is stopped. I actually thought it was a bug when i was trying to test a custom process_stream_data function and called BinanceWebSocketApiManager.stop_stream() after a few seconds to inspect my processed data, only to get a Process finished with exit code 0 in my console and my data gone

Or could the problem be on my end and the interpreter is not supposed to die when sys.exit() is called?

oliver-zehentleitner commented 3 years ago

Hello! sys.exit() does close the thread where it is called from. If a stream has an error, we catch the exception and decide what to do:

  1. is the stream repairable? then we close the thread restart the stream in a new thread.
  2. the stream is not repairable? (wrong api secrets) then we close the thread too, but dont restart it.

Its not the complete interpreter that get killed, only one thread! Its the aim of this lib, that you dont need to care about the streams, its managed by the lib.

If you want an exception if a stream is not repairable use: throw_exception_if_unrepairable parameter.

Its just a feeling, but I think your problem is that you use a process_stream_data() callback, better you use the stream_buffer. you should find enough information about using stream_buffer in the example files.

Best regards, Oliver

tropo84 commented 3 years ago

Ah ok, then the problem seems to be on my end aparently. Because for me, it seems that sys.exit() does kill the complete interpreter, no matter from where it's called. It is also not related to the custom process_stream_data() callback, as it happens as well when i simply stop a stream. Here's a code snipped, which would kill my interpreter when i execute the file with that code:

from unicorn_binance_websocket_api.unicorn_binance_websocket_api_manager import BinanceWebSocketApiManager
import time

websocket_manager = BinanceWebSocketApiManager(throw_exception_if_unrepairable=True, output_default='UnicornFy')

id = websocket_manager.create_stream(channels='depth', markets='BTCUSDT')

time.sleep(5)

websocket_manager.stop_stream(id)

That's what i get:

Type 'copyright', 'credits' or 'license' for more information
IPython 7.12.0 -- An enhanced Interactive Python. Type '?' for help.
PyDev console: using IPython 7.12.0

Python 3.7.6 (default, Jan  8 2020, 20:23:39) [MSC v.1916 64 bit (AMD64)] on win32
In[2]: runfile('C:/Users/Steffen/AppData/Roaming/JetBrains/PyCharm2020.3/scratches/scratch_8.py', wdir='C:/Users/Steffen/AppData/Roaming/JetBrains/PyCharm2020.3/scratches')

Process finished with exit code 0

Here's another example where an exception is thrown in process_stream_data

from unicorn_binance_websocket_api.unicorn_binance_websocket_api_manager import BinanceWebSocketApiManager
import time

def raise_some_exceptions(stream_msg, stream_buffer_name=None):
    raise ValueError('some exception')

websocket_manager = BinanceWebSocketApiManager(process_stream_data=raise_some_exceptions, throw_exception_if_unrepairable=True,
                                               output_default='UnicornFy')

id = websocket_manager.create_stream(channels='depth', markets='BTCUSDT')

time.sleep(5)

websocket_manager.stop_stream(id)

Leading to:

Type 'copyright', 'credits' or 'license' for more information
IPython 7.12.0 -- An enhanced Interactive Python. Type '?' for help.
PyDev console: using IPython 7.12.0

Python 3.7.6 (default, Jan  8 2020, 20:23:39) [MSC v.1916 64 bit (AMD64)] on win32
In[2]: runfile('C:/Users/Steffen/AppData/Roaming/JetBrains/PyCharm2020.3/scratches/scratch_8.py', wdir='C:/Users/Steffen/AppData/Roaming/JetBrains/PyCharm2020.3/scratches')
ERROR:root:BinanceWebSocketApiSocket.start_socket(56177164-145a-48f6-88d9-bdc808cc6708, ['depth'], ['btcusdt']) - Exception General Exception - error_msg: some exception
CRITICAL:root:BinanceWebSocketApiManager.stream_is_crashing(56177164-145a-48f6-88d9-bdc808cc6708)

Process finished with exit code 1

In both cases, my console/interpreter is dead.

Can you confirm that this is not supposed to happen?

I'm on windows, using pycharm with an IPython console (if that's relevant)

tropo84 commented 3 years ago

The problem seems to be with PyCharm! Running the first example in a python console, or in an ipython console, which are started from the terminal and not in PyCharm does not kill the interpreter!

So it is not at all related to your package. Sorry for the noise! In case i find a solution, for pycharm, i'll post it here. But closing for now.

oliver-zehentleitner commented 3 years ago

Great! Your welcome!