Avoid using 'terminate' on the download thread
This commit is contained in:
@@ -5,6 +5,7 @@ from threads import DownloadThread, ThreadStatus
|
|||||||
from utilities import pop_up, resource_path
|
from utilities import pop_up, resource_path
|
||||||
from constants import Constants, Messages
|
from constants import Constants, Messages
|
||||||
|
|
||||||
|
|
||||||
Ui_Download_window, _ = uic.loadUiType(
|
Ui_Download_window, _ = uic.loadUiType(
|
||||||
resource_path("download_db_window.ui")
|
resource_path("download_db_window.ui")
|
||||||
)
|
)
|
||||||
@@ -14,6 +15,7 @@ class DownloadWindow(QWidget, Ui_Download_window):
|
|||||||
"""Subclass QWidget and Ui_Download_window. It is the window displayed during the database download."""
|
"""Subclass QWidget and Ui_Download_window. It is the window displayed during the database download."""
|
||||||
|
|
||||||
complete = pyqtSignal()
|
complete = pyqtSignal()
|
||||||
|
closed = pyqtSignal()
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
"""Initialize the window."""
|
"""Initialize the window."""
|
||||||
@@ -38,6 +40,7 @@ class DownloadWindow(QWidget, Ui_Download_window):
|
|||||||
self._download_thread = DownloadThread()
|
self._download_thread = DownloadThread()
|
||||||
self._download_thread.finished.connect(self._wait_close)
|
self._download_thread.finished.connect(self._wait_close)
|
||||||
self._download_thread.progress.connect(self._display_progress)
|
self._download_thread.progress.connect(self._display_progress)
|
||||||
|
self.closed.connect(self._download_thread.set_exit)
|
||||||
self.cancel_btn.clicked.connect(self._terminate_process)
|
self.cancel_btn.clicked.connect(self._terminate_process)
|
||||||
|
|
||||||
def start_download(self):
|
def start_download(self):
|
||||||
@@ -61,12 +64,16 @@ class DownloadWindow(QWidget, Ui_Download_window):
|
|||||||
elif progress == Constants.EXTRACTING_CODE:
|
elif progress == Constants.EXTRACTING_CODE:
|
||||||
self.status_lbl.setText(Constants.EXTRACTING_MSG + '\n')
|
self.status_lbl.setText(Constants.EXTRACTING_MSG + '\n')
|
||||||
|
|
||||||
|
def _stop_thread(self):
|
||||||
|
"""Ask the download thread to stop."""
|
||||||
|
if self._download_thread.isRunning():
|
||||||
|
self.closed.emit()
|
||||||
|
self._download_thread.wait()
|
||||||
|
|
||||||
@pyqtSlot()
|
@pyqtSlot()
|
||||||
def _terminate_process(self):
|
def _terminate_process(self):
|
||||||
"""Terminate the download thread and close."""
|
"""Terminate the download thread and close."""
|
||||||
if self._download_thread.isRunning():
|
self._stop_thread()
|
||||||
self._download_thread.terminate()
|
|
||||||
self._download_thread.wait()
|
|
||||||
self.close()
|
self.close()
|
||||||
|
|
||||||
@pyqtSlot()
|
@pyqtSlot()
|
||||||
@@ -84,7 +91,5 @@ class DownloadWindow(QWidget, Ui_Download_window):
|
|||||||
|
|
||||||
def reject(self):
|
def reject(self):
|
||||||
"""Extends QWidget.reject. Terminate the download thread."""
|
"""Extends QWidget.reject. Terminate the download thread."""
|
||||||
if self._download_thread.isRunning():
|
self._stop_thread()
|
||||||
self._download_thread.terminate()
|
|
||||||
self._download_thread.wait()
|
|
||||||
super().reject()
|
super().reject()
|
||||||
|
|||||||
58
threads.py
58
threads.py
@@ -41,16 +41,17 @@ class DownloadThread(BaseDownloadThread):
|
|||||||
"""Subclass BaseDownloadThread. Download the database, images and audio samples."""
|
"""Subclass BaseDownloadThread. Download the database, images and audio samples."""
|
||||||
|
|
||||||
progress = pyqtSignal(int, float)
|
progress = pyqtSignal(int, float)
|
||||||
CHUNK = 1024**2
|
_CHUNK = 1024**2
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
"""Just call super().__init__."""
|
"""Just call super().__init__."""
|
||||||
self.db = None
|
self._db = None
|
||||||
|
self._exit_call = False
|
||||||
super().__init__()
|
super().__init__()
|
||||||
|
|
||||||
def _pretty_len(self, byte_obj):
|
def _pretty_len(self, byte_obj):
|
||||||
"""Return a well-formatted number of downloaded MB."""
|
"""Return a well-formatted number of downloaded MB."""
|
||||||
mega = len(byte_obj) / self.CHUNK
|
mega = len(byte_obj) / self._CHUNK
|
||||||
if mega.is_integer():
|
if mega.is_integer():
|
||||||
return int(mega)
|
return int(mega)
|
||||||
else:
|
else:
|
||||||
@@ -59,40 +60,51 @@ class DownloadThread(BaseDownloadThread):
|
|||||||
def _get_download_speed(self, data, delta):
|
def _get_download_speed(self, data, delta):
|
||||||
"""Return the download speed in MB/s."""
|
"""Return the download speed in MB/s."""
|
||||||
return round(
|
return round(
|
||||||
(len(data) / self.CHUNK) / delta, 2
|
(len(data) / self._CHUNK) / delta, 2
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def set_exit(self):
|
||||||
|
self._exit_call = True
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
"""Override QThread.run. Download the database, images and audio samples.
|
"""Override QThread.run. Download the database, images and audio samples.
|
||||||
|
|
||||||
Handle all possible exceptions. Also extract the files
|
Handle all possible exceptions. Also extract the files
|
||||||
in the local folder."""
|
in the local folder."""
|
||||||
self.status = ThreadStatus.UNDEFINED
|
self.status = ThreadStatus.UNDEFINED
|
||||||
self.db = None
|
self._db = None
|
||||||
raw_data = bytes(0)
|
raw_data = bytes(0)
|
||||||
try:
|
try:
|
||||||
self.db = urllib3.PoolManager().request(
|
self._db = urllib3.PoolManager().request(
|
||||||
'GET',
|
'GET',
|
||||||
Database.LINK_LOC,
|
Database.LINK_LOC,
|
||||||
preload_content=False
|
preload_content=False,
|
||||||
|
timeout=4.0
|
||||||
)
|
)
|
||||||
while True:
|
while True:
|
||||||
start = time()
|
start = time()
|
||||||
data = self.db.read(self.CHUNK)
|
try:
|
||||||
delta = time() - start
|
data = self._db.read(self._CHUNK)
|
||||||
if not data:
|
except Exception:
|
||||||
break
|
raise
|
||||||
raw_data += data
|
else:
|
||||||
self.progress.emit(
|
delta = time() - start
|
||||||
self._pretty_len(raw_data),
|
if not data:
|
||||||
self._get_download_speed(data, delta)
|
break
|
||||||
)
|
raw_data += data
|
||||||
self.db.release_conn()
|
self.progress.emit(
|
||||||
|
self._pretty_len(raw_data),
|
||||||
|
self._get_download_speed(data, delta)
|
||||||
|
)
|
||||||
|
if self._exit_call:
|
||||||
|
self._exit_call = False
|
||||||
|
self._db.release_conn()
|
||||||
|
return
|
||||||
except Exception: # No internet connection.
|
except Exception: # No internet connection.
|
||||||
self.db.release_conn()
|
self._db.release_conn()
|
||||||
self.status = ThreadStatus.NO_CONNECTION_ERR
|
self.status = ThreadStatus.NO_CONNECTION_ERR
|
||||||
return
|
return
|
||||||
if self.db.status != 200:
|
if self._db.status != 200:
|
||||||
self.status = ThreadStatus.BAD_DOWNLOAD_ERR
|
self.status = ThreadStatus.BAD_DOWNLOAD_ERR
|
||||||
return
|
return
|
||||||
try:
|
try:
|
||||||
@@ -115,14 +127,6 @@ class DownloadThread(BaseDownloadThread):
|
|||||||
else:
|
else:
|
||||||
self.status = ThreadStatus.OK
|
self.status = ThreadStatus.OK
|
||||||
|
|
||||||
def terminate(self):
|
|
||||||
"""Extend QThread.terminate.
|
|
||||||
|
|
||||||
Release the connection in case of termination."""
|
|
||||||
if self.db is not None:
|
|
||||||
self.db.release_conn()
|
|
||||||
super().terminate()
|
|
||||||
|
|
||||||
|
|
||||||
class _AsyncDownloader:
|
class _AsyncDownloader:
|
||||||
"""Mixin class for asynchronous threads."""
|
"""Mixin class for asynchronous threads."""
|
||||||
|
|||||||
Reference in New Issue
Block a user