0

I have scripts running 24/7 that sometimes get stuck when a thread in concurrent.futures gets no response for a request. I use concurrent.futures Threadpools to simultaneously send requests to a Broker. So, every thread is something simple like a function that requests the account balance or sends an order. I need those Threads either executed or failed in order to move on, because every further action requires the data acquired through the threads before.

Below is an example of two simple order functions and the concurrent futures.

def sell_orders_0():
    order = client.new_order(symbol = ticker, side = 'SELL', type = 'LIMIT_MAKER', quantity = xquantity, price = xprice)
def buy_orders_0():
    order = client.new_order(symbol = ticker, side = 'SELL', type = 'LIMIT_MAKER', quantity = xquantity, price = xprice)

with concurrent.futures.ThreadPoolExecutor() as executor:
    sells_0 = executor.submit(sell_orders_0)
    buys_0 = executor.submit(buy_orders_0)

The hanging Threads module prints out which thread hangs and why:

Thread 139646566659840 "ThreadPoolExecutor-666849_1" hangs -                                                                                                                                                                                     
    File "/usr/lib/python3.9/threading.py", line 912, in _bootstrap                                                                                                                                                                          
            self._bootstrap_inner()                                                                                                                                                                                                          
    File "/usr/lib/python3.9/threading.py", line 954, in _bootstrap_inner                                                                                                                                                                    
            self.run()                                                                                                                                                                                                                       
    File "/usr/lib/python3.9/threading.py", line 892, in run                                                                                                                                                                                 
            self._target(*self._args, **self._kwargs)                                                                                                                                                                                        
    File "/usr/lib/python3.9/concurrent/futures/thread.py", line 77, in _worker                                                                                                                                                              
            work_item.run()                                                                                                                                                                                                                  
    File "/usr/lib/python3.9/concurrent/futures/thread.py", line 52, in run                                                                                                                                                                  
            result = self.fn(*self.args, **self.kwargs)                                                                                                                                                                                      
    File "/home/user/binance_bot.py", line 1346, in sell_orders_3                                                                                                                                                                 
            order = client.new_order(symbol = ticker, side = 'SELL', type = 'LIMIT_MAKER', quantity = xquantity, price = xprice)                                                                                                             
    File "/home/user/.local/lib/python3.9/site-packages/binance/spot/trade.py", line 68, in new_order                                                                                                                                   
            return self.sign_request("POST", url_path, params)                                                                                                                                                                               
    File "/home/user/.local/lib/python3.9/site-packages/binance/api.py", line 83, in sign_request                                                                                                                                       
            return self.send_request(http_method, url_path, payload)                                                                                                                                                                         
    File "/home/user/.local/lib/python3.9/site-packages/binance/api.py", line 115, in send_request                                                                                                                                      
            response = self._dispatch_request(http_method)(**params)                                                                                                                                                                         
    File "/home/user/.local/lib/python3.9/site-packages/requests/sessions.py", line 635, in post                                                                                                                                        
            return self.request("POST", url, data=data, json=json, **kwargs)                                                                                                                                                                 
    File "/home/user/.local/lib/python3.9/site-packages/requests/sessions.py", line 587, in request                                                                                                                                     
            resp = self.send(prep, **send_kwargs)                                                                                                                                                                                            
    File "/home/user/.local/lib/python3.9/site-packages/requests/sessions.py", line 701, in send                                                                                                                                        
            r = adapter.send(request, **kwargs)                                                                                                                                                                                              
    File "/home/user/.local/lib/python3.9/site-packages/requests/adapters.py", line 489, in send                                                                                                                                        
            resp = conn.urlopen(                                                                                                                                                                                                             
    File "/home/user/.local/lib/python3.9/site-packages/urllib3/connectionpool.py", line 703, in urlopen                                                                                                                                
            httplib_response = self._make_request(                                                                                                                                                                                           
    File "/home/user/.local/lib/python3.9/site-packages/urllib3/connectionpool.py", line 444, in _make_request                                                                                                                          
            httplib_response = conn.getresponse()                                                                                                                                                                                            
    File "/usr/lib/python3.9/http/client.py", line 1347, in getresponse                                                                                                                                                                      
            response.begin()                                                                                                                                                                                                                 
    File "/usr/lib/python3.9/http/client.py", line 307, in begin                                                                                                                                                                             
            version, status, reason = self._read_status()                                                                                                                                                                                    
    File "/usr/lib/python3.9/http/client.py", line 268, in _read_status                                                                                                                                                                      
            line = str(self.fp.readline(_MAXLINE + 1), "iso-8859-1") 
File "/usr/lib/python3.9/socket.py", line 704, in readinto                                                                                                                                                                       [0/1893]
            return self._sock.recv_into(b)
    File "/usr/lib/python3.9/ssl.py", line 1241, in recv_into
            return self.read(nbytes, buffer)
    File "/usr/lib/python3.9/ssl.py", line 1099, in read 
            return self._sslobj.read(len, buffer)

Thread 139646533089024 "ThreadPoolExecutor-666849_0" hangs - 
    File "/usr/lib/python3.9/threading.py", line 912, in _bootstrap
            self._bootstrap_inner()
    File "/usr/lib/python3.9/threading.py", line 954, in _bootstrap_inner
            self.run()
    File "/usr/lib/python3.9/threading.py", line 892, in run
            self._target(*self._args, **self._kwargs)
    File "/usr/lib/python3.9/concurrent/futures/thread.py", line 77, in _worker
            work_item.run()
    File "/usr/lib/python3.9/concurrent/futures/thread.py", line 52, in run
            result = self.fn(*self.args, **self.kwargs)
    File "/home/user/binance_bot.py", line 1298, in sell_orders_0
            order = client.new_order(symbol = ticker, side = 'SELL', type = 'LIMIT_MAKER', quantity = xquantity, price = xprice)
    File "/home/user/.local/lib/python3.9/site-packages/binance/spot/trade.py", line 68, in new_order
            return self.sign_request("POST", url_path, params)
    File "/home/user/.local/lib/python3.9/site-packages/binance/api.py", line 83, in sign_request
            return self.send_request(http_method, url_path, payload)
    File "/home/user/.local/lib/python3.9/site-packages/binance/api.py", line 115, in send_request
            response = self._dispatch_request(http_method)(**params)
    File "/home/user/.local/lib/python3.9/site-packages/requests/sessions.py", line 635, in post
            return self.request("POST", url, data=data, json=json, **kwargs)
    File "/home/user/.local/lib/python3.9/site-packages/requests/sessions.py", line 587, in request
            resp = self.send(prep, **send_kwargs)
    File "/home/user/.local/lib/python3.9/site-packages/requests/sessions.py", line 701, in send
            r = adapter.send(request, **kwargs)
    File "/home/user/.local/lib/python3.9/site-packages/requests/adapters.py", line 489, in send
            resp = conn.urlopen(
    File "/home/user/.local/lib/python3.9/site-packages/urllib3/connectionpool.py", line 703, in urlopen
            httplib_response = self._make_request(
    File "/home/user/.local/lib/python3.9/site-packages/urllib3/connectionpool.py", line 444, in _make_request
            httplib_response = conn.getresponse()
    File "/usr/lib/python3.9/http/client.py", line 1347, in getresponse
            response.begin()
    File "/usr/lib/python3.9/http/client.py", line 307, in begin
            version, status, reason = self._read_status()
    File "/usr/lib/python3.9/http/client.py", line 268, in _read_status
            line = str(self.fp.readline(_MAXLINE + 1), "iso-8859-1")
    File "/usr/lib/python3.9/socket.py", line 704, in readinto
            return self._sock.recv_into(b)
    File "/usr/lib/python3.9/ssl.py", line 1241, in recv_into
            return self.read(nbytes, buffer)
    File "/usr/lib/python3.9/ssl.py", line 1099, in read 
            return self._sslobj.read(len, buffer)
---------Thread 139646838966080 "MainThread" hangs --------- 
    File "/home/user/binance_bot.py", line 1596, in <module>
            buys_0 = executor.submit(buy_orders_0)
    File "/usr/lib/python3.9/concurrent/futures/_base.py", line 628, in __exit__
            self.shutdown(wait=True)
    File "/usr/lib/python3.9/concurrent/futures/thread.py", line 229, in shutdown
            t.join()
    File "/usr/lib/python3.9/threading.py", line 1033, in join
            self._wait_for_tstate_lock()
    File "/usr/lib/python3.9/threading.py", line 1049, in _wait_for_tstate_lock
            elif lock.acquire(block, timeout):

How could i make my code nonblocking?

I already asked how i could raise an exception when my code hangs, but that's not possible since cancelling a running Thread from outside is impossible.

PyNoob
  • 9
  • 3

1 Answers1

0

You need to add a timeout argument to the requests.post() call, presumably somewhere in binance/api.py.

https://requests.readthedocs.io/en/latest/user/advanced/#timeouts describes:

Most requests to external servers should have a timeout attached, in case the server is not responding in a timely manner. By default, requests do not time out unless a timeout value is set explicitly. Without a timeout, your code may hang for minutes or more.

vashekcz
  • 561
  • 1
  • 4
  • 16