Обработка ошибок подключения к QUIK
This commit is contained in:
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
__pycache__
|
||||||
63
QuikPy.py
63
QuikPy.py
@@ -37,10 +37,14 @@ class QuikPy(metaclass=Singleton): # Singleton класс
|
|||||||
fragments = [] # Будем получать ответ в виде списка фрагментов. Они могут быть разной длины. Ответ может состоять из нескольких фрагментов
|
fragments = [] # Будем получать ответ в виде списка фрагментов. Они могут быть разной длины. Ответ может состоять из нескольких фрагментов
|
||||||
while getattr(currentThread, 'process', True): # Пока поток нужен
|
while getattr(currentThread, 'process', True): # Пока поток нужен
|
||||||
while True: # Пока есть что-то в буфере ответов
|
while True: # Пока есть что-то в буфере ответов
|
||||||
fragment = socketCallbacks.recv(self.bufferSize) # Читаем фрагмент из буфера
|
try:
|
||||||
fragments.append(fragment.decode('cp1251')) # Переводим фрагмент в Windows кодировку 1251, добавляем в список
|
fragment = socketCallbacks.recv(self.bufferSize) # Читаем фрагмент из буфера
|
||||||
if len(fragment) < self.bufferSize: # Если в принятом фрагменте данных меньше чем размер буфера
|
except ConnectionResetError:
|
||||||
break # то, возможно, это был последний фрагмент, выходим из чтения буфера
|
print("Соединение сброшено")
|
||||||
|
else:
|
||||||
|
fragments.append(fragment.decode('cp1251')) # Переводим фрагмент в Windows кодировку 1251, добавляем в список
|
||||||
|
if len(fragment) < self.bufferSize: # Если в принятом фрагменте данных меньше чем размер буфера
|
||||||
|
break # то, возможно, это был последний фрагмент, выходим из чтения буфера
|
||||||
data = ''.join(fragments) # Собираем список фрагментов в строку
|
data = ''.join(fragments) # Собираем список фрагментов в строку
|
||||||
dataList = data.split('\n') # Одновременно могут прийти несколько функций обратного вызова, разбираем их по одной
|
dataList = data.split('\n') # Одновременно могут прийти несколько функций обратного вызова, разбираем их по одной
|
||||||
fragments = [] # Сбрасываем фрагменты. Если последнюю строку не сможем разобрать, то занесем ее сюда
|
fragments = [] # Сбрасываем фрагменты. Если последнюю строку не сможем разобрать, то занесем ее сюда
|
||||||
@@ -111,10 +115,32 @@ class QuikPy(metaclass=Singleton): # Singleton класс
|
|||||||
def ProcessRequest(self, Request):
|
def ProcessRequest(self, Request):
|
||||||
"""Отправляем запрос в QUIK, получаем ответ из QUIK"""
|
"""Отправляем запрос в QUIK, получаем ответ из QUIK"""
|
||||||
rawData = json.dumps(Request) # Переводим запрос в формат JSON
|
rawData = json.dumps(Request) # Переводим запрос в формат JSON
|
||||||
self.socketRequests.sendall(f'{rawData}\r\n'.encode()) # Отправляем запрос в QUIK
|
# self.socketRequests.settimeout(1)
|
||||||
|
# print(self.socketRequests.timeout)
|
||||||
|
# self.socketRequests.sendall(f'{rawData}\r\n'.encode()) # Отправляем запрос в QUIK
|
||||||
|
try:
|
||||||
|
self.socketRequests.sendall(f'{rawData}\r\n'.encode()) # Отправляем запрос в QUIK
|
||||||
|
except Exception:
|
||||||
|
# raise TimeoutError("Истёк таймаут подключения к QUIK")
|
||||||
|
print("Истёк таймаут подключения к QUIK")
|
||||||
|
data = {"data": "error"}
|
||||||
|
return data
|
||||||
fragments = [] # Гораздо быстрее получать ответ в виде списка фрагментов
|
fragments = [] # Гораздо быстрее получать ответ в виде списка фрагментов
|
||||||
|
|
||||||
while True: # Пока фрагменты есть в буфере
|
while True: # Пока фрагменты есть в буфере
|
||||||
fragment = self.socketRequests.recv(self.bufferSize) # Читаем фрагмент из буфера
|
# print(fragments)
|
||||||
|
try:
|
||||||
|
fragment = self.socketRequests.recv(self.bufferSize) # Читаем фрагмент из буфера
|
||||||
|
assert len(fragment) > 0
|
||||||
|
except (TimeoutError, AssertionError):
|
||||||
|
print("Истёк таймаут подключения к QUIK")
|
||||||
|
data = {"data": "error"}
|
||||||
|
return data
|
||||||
|
except ConnectionResetError:
|
||||||
|
print("Соединение сброшено")
|
||||||
|
data = {"data": "error"}
|
||||||
|
return data
|
||||||
|
|
||||||
fragments.append(fragment.decode('cp1251')) # Переводим фрагмент в Windows кодировку 1251, добавляем в список
|
fragments.append(fragment.decode('cp1251')) # Переводим фрагмент в Windows кодировку 1251, добавляем в список
|
||||||
if len(fragment) < self.bufferSize: # Если в принятом фрагменте данных меньше чем размер буфера
|
if len(fragment) < self.bufferSize: # Если в принятом фрагменте данных меньше чем размер буфера
|
||||||
data = ''.join(fragments) # Собираем список фрагментов в строку
|
data = ''.join(fragments) # Собираем список фрагментов в строку
|
||||||
@@ -125,7 +151,7 @@ class QuikPy(metaclass=Singleton): # Singleton класс
|
|||||||
|
|
||||||
# Инициализация и вход
|
# Инициализация и вход
|
||||||
|
|
||||||
def __init__(self, Host='127.0.0.1', RequestsPort=34130, CallbacksPort=34131):
|
def __init__(self, Host='127.0.0.1', RequestsPort=34130, CallbacksPort=34131, connection_timeout=None):
|
||||||
"""Инициализация"""
|
"""Инициализация"""
|
||||||
# 2.2. Функции обратного вызова
|
# 2.2. Функции обратного вызова
|
||||||
self.OnFirm = self.DefaultHandler # 1. Новая фирма
|
self.OnFirm = self.DefaultHandler # 1. Новая фирма
|
||||||
@@ -162,17 +188,25 @@ class QuikPy(metaclass=Singleton): # Singleton класс
|
|||||||
self.RequestsPort = RequestsPort # Порт для отправки запросов и получения ответов
|
self.RequestsPort = RequestsPort # Порт для отправки запросов и получения ответов
|
||||||
self.CallbacksPort = CallbacksPort # Порт для функций обратного вызова
|
self.CallbacksPort = CallbacksPort # Порт для функций обратного вызова
|
||||||
self.socketRequests = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # Создаем соединение для запросов
|
self.socketRequests = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # Создаем соединение для запросов
|
||||||
self.socketRequests.connect((self.Host, self.RequestsPort)) # Открываем соединение для запросов
|
if connection_timeout is not None:
|
||||||
|
self.socketRequests.settimeout(connection_timeout)
|
||||||
|
self.callbackThread = threading.Thread(target=self.CallbackHandler,
|
||||||
|
name='CallbackThread') # Создаем поток обработки функций обратного вызова
|
||||||
|
|
||||||
|
try:
|
||||||
|
self.socketRequests.connect((self.Host, self.RequestsPort)) # Открываем соединение для запросов
|
||||||
|
except TimeoutError:
|
||||||
|
raise ConnectionError("Истёк таймаут подключения к QUIK")
|
||||||
|
else:
|
||||||
|
self.callbackThread.start() # Запускаем поток
|
||||||
|
|
||||||
self.callbackThread = threading.Thread(target=self.CallbackHandler, name='CallbackThread') # Создаем поток обработки функций обратного вызова
|
|
||||||
self.callbackThread.start() # Запускаем поток
|
|
||||||
|
|
||||||
def __enter__(self):
|
def __enter__(self):
|
||||||
"""Вход в класс, например, с with"""
|
"""Вход в класс, например, с with"""
|
||||||
return self
|
return self
|
||||||
|
|
||||||
# Фукнции связи с QuikSharp
|
# Фукнции связи с QuikSharp
|
||||||
|
|
||||||
def Ping(self, TransId=0):
|
def Ping(self, TransId=0):
|
||||||
"""Проверка соединения. Отправка ping. Получение pong"""
|
"""Проверка соединения. Отправка ping. Получение pong"""
|
||||||
return self.ProcessRequest({'data': 'Ping', 'id': TransId, 'cmd': 'ping', 't': ''})
|
return self.ProcessRequest({'data': 'Ping', 'id': TransId, 'cmd': 'ping', 't': ''})
|
||||||
@@ -221,7 +255,7 @@ class QuikPy(metaclass=Singleton): # Singleton класс
|
|||||||
# isDarkTheme - 9. Тема оформления. true - тёмная, false - светлая
|
# isDarkTheme - 9. Тема оформления. true - тёмная, false - светлая
|
||||||
|
|
||||||
# Сервисные функции QuikSharp
|
# Сервисные функции QuikSharp
|
||||||
|
|
||||||
def MessageInfo(self, Message, TransId=0): # В QUIK LUA message icon_type=1
|
def MessageInfo(self, Message, TransId=0): # В QUIK LUA message icon_type=1
|
||||||
"""Отправка информационного сообщения в терминал QUIK"""
|
"""Отправка информационного сообщения в терминал QUIK"""
|
||||||
return self.ProcessRequest({'data': Message, 'id': TransId, 'cmd': 'message', 't': ''})
|
return self.ProcessRequest({'data': Message, 'id': TransId, 'cmd': 'message', 't': ''})
|
||||||
@@ -250,7 +284,7 @@ class QuikPy(metaclass=Singleton): # Singleton класс
|
|||||||
def GetTradeAccount(self, ClassCode, TransId=0):
|
def GetTradeAccount(self, ClassCode, TransId=0):
|
||||||
"""Торговый счет для запрашиваемого кода класса"""
|
"""Торговый счет для запрашиваемого кода класса"""
|
||||||
return self.ProcessRequest({'data': ClassCode, 'id': TransId, 'cmd': 'getTradeAccount', 't': ''})
|
return self.ProcessRequest({'data': ClassCode, 'id': TransId, 'cmd': 'getTradeAccount', 't': ''})
|
||||||
|
|
||||||
def GetAllOrders(self, TransId=0):
|
def GetAllOrders(self, TransId=0):
|
||||||
"""Таблица заявок (вся)"""
|
"""Таблица заявок (вся)"""
|
||||||
return self.ProcessRequest({'data': f'', 'id': TransId, 'cmd': 'get_orders', 't': ''})
|
return self.ProcessRequest({'data': f'', 'id': TransId, 'cmd': 'get_orders', 't': ''})
|
||||||
@@ -332,7 +366,7 @@ class QuikPy(metaclass=Singleton): # Singleton класс
|
|||||||
def GetClassSecurities(self, ClassCode, TransId=0): # 3
|
def GetClassSecurities(self, ClassCode, TransId=0): # 3
|
||||||
"""Список инструментов класса"""
|
"""Список инструментов класса"""
|
||||||
return self.ProcessRequest({'data': ClassCode, 'id': TransId, 'cmd': 'getClassSecurities', 't': ''})
|
return self.ProcessRequest({'data': ClassCode, 'id': TransId, 'cmd': 'getClassSecurities', 't': ''})
|
||||||
|
|
||||||
# Функции для обращения к спискам доступных параметров QuikSharp
|
# Функции для обращения к спискам доступных параметров QuikSharp
|
||||||
|
|
||||||
def GetOptionBoard(self, ClassCode, SecCode, TransId=0):
|
def GetOptionBoard(self, ClassCode, SecCode, TransId=0):
|
||||||
@@ -590,3 +624,4 @@ class QuikPy(metaclass=Singleton): # Singleton класс
|
|||||||
|
|
||||||
def __del__(self):
|
def __del__(self):
|
||||||
self.CloseConnectionAndThread() # Закрываем соединение для запросов и поток обработки функций обратного вызова
|
self.CloseConnectionAndThread() # Закрываем соединение для запросов и поток обработки функций обратного вызова
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user