Я занимаюсь рефакторингом некоторого старого Python кода, который я унаследовал и долгое время исправлял go. Это программа GUI, которая порождает несколько процессов, которые используют одну службу AsyncDownloadService для загрузки данных из различных источников. AsyncDownloadService запускает потоки с помощью requests.get
и обратных вызовов, чтобы не блокировать пользовательский интерфейс.
Я сделал AsyncDownloadService классом stati c, и он работал нормально.
Но потом я подумал, что это ' Я должен быть умным, чтобы применить шаблон Singleton, один раз создать экземпляр класса и с этого момента вызывать его везде, где он мне нужен, с помощью AsyncDownloadService()
, без необходимости вводить зависимость. Я не уверен, что это на самом деле хорошая идея, но, применив шаблон Singleton, я заметил, что мое приложение не закрывается немедленно, когда его попросят (Gtk.main_quit()
. Скорее всего, оно ждало, пока requests.get
потоки будут fini sh.
Однако я не заметил такого поведения, когда служба была классом c stati. Есть идеи, почему это так?
Новый код (Singleton):
class SingletonType(type):
_instances = {}
def __call__(cls, *args, **kwargs):
if cls not in cls._instances:
cls._instances[cls] = super(SingletonType, cls).__call__(*args, **kwargs)
return cls._instances[cls]
class AsyncDownloadService(metaclass=SingletonType):
def execute(self, command, response_handler):
def _callback_with_args(response, **kwargs):
command.response = response
response_handler(command)
kwargs = {
'command': command,
'callback': _callback_with_args
}
thread = Thread(target=self.download, kwargs=kwargs)
thread.start()
def download(self, command, callback):
kwargs = {
'timeout': command.timeout,
'hooks': {'response': callback}
}
try:
get(command.url, **kwargs)
except exceptions.RequestException as e:
command.error = "Connection error " + str(e)
callback(None)
Старый код (stati c class):
class AsyncDownloadService():
def execute(self, command, response_handler):
def _callback_with_args(response, **kwargs):
command.response = response
response_handler(command)
kwargs = {
'command': command,
'callback': _callback_with_args
}
thread = Thread(target=AsyncDownloadService.download, kwargs=kwargs)
thread.start()
@staticmethod
def download(command, callback):
kwargs = {
'timeout': command.timeout,
'hooks': {'response': callback}
}
try:
get(command.url, **kwargs)
except exceptions.RequestException as e:
command.error = "Connection error " + str(e)
callback(None)