Работая с python3, у меня есть следующие классы
class RESTApi:
def __init__(self):
self.connection = # Create connection
def hello_world(self):
print("Hello World !!")
... # More methods
class BaseVM:
def __init__(self):
self.restapi = RESTApi()
def _refresh_restapi_connection(self):
self.restapi = # Reconnect
class MyClass(BaseVM):
def __init__(self, *args):
BaseVM.__init__(self, *args)
def create_user(self, usr, pwd):
self.restapi.create_user(usr, pwd)
MyClass — это место, где я взаимодействую с существующими классами, и я могу изменить код в MyClass, но не в других классах.
Проблема, с которой я сталкиваюсь, заключается в том, что соединение REST очищается, когда оно остается бездействующим. Поэтому мне нужно реализовать вызов для обновления соединения REST (_refresh_restapi_connection) всякий раз, когда «self.restapi.XYZ» терпит неудачу.
И я хочу, чтобы это было автоматически сделано в попытке... кроме. Такие методы, как «create_user» и т. д., не должны знать, что было переподключение.
Поскольку я не могу изменить другие классы, я пытаюсь создать оболочку для вызовов self.restapi
Что-то типа:
class RestRetry:
'''
Wrapper over RESTApi class instance with retries
'''
def __init__(self, vm):
self._restapi = vm.restapi
def __getattr__(self, attrb):
return self.rest_retry(attrb)
def rest_retry(self, attrb):
def _retry():
try:
# class REST API with retries
result = getattr(self._restapi, attrb)
except:
self._refresh_restapi_connection()
return getattr(self._restapi, attrb)
else:
return result
return _retry
И тогда MyClass
будет
def __init__(self, *args):
BaseVM.__init__(self, *args)
self.restapi = RestRetry()
Хотя это не работает
Может быть, я упускаю что-то очень простое или, может быть, пытаюсь решить это неправильно.
Можете ли вы уточнить, почему это происходит: «Проблема, с которой я столкнулся, заключается в том, что соединение REST очищается, когда оно остается бездействующим»? Что именно означает «когда не используется»?
Это длительные тесты, которые создают REST-сеанс/подключение к серверу. Есть места, где «следующий запрос через REST» происходит после длительного интервала. К этому времени сессия очищается сервером, так как считается незанятой.
Это то, что я в итоге написал. Пришлось изменить имя атрибута в MyClass
, чего я не хотел, но не мог заставить его работать без этого
class RestRetry:
'''
Wrapper over RESTApi class instance with retries
'''
def __init__(self, vm):
self._vm= vm
def __getattr__(self, attrb):
return self.rest_retry(attrb)
def rest_retry(self, attrb):
def _retry(*args, **kwargs):
try:
# class REST API with retries though
result = getattr(self._vm.restapi, attrb)(*args, **kwargs)
except:
self._vm._refresh_restapi_connection()
return getattr(self._vm.restapi, attrb)(*args, **kwargs)
else:
return result
return _retry
А потом в MyClass
def __init__(self):
BaseVM.__init__(self)
self._restapi = self.RestRetry(self)
def any_method(self):
self._restapi.hello_world()
Для начала вы должны использовать
super()
при создании подклассов. Вам также следует рассмотреть возможность инверсии зависимостей дляBaseVM
или, по крайней мере, создания подклассовRESTApi
.