[cli] use status queue to print progress

This commit is contained in:
ChemicalXandco 2021-02-06 10:32:27 +00:00
parent 1cf2d7e6e7
commit c1db2b9f07
4 changed files with 53 additions and 31 deletions

View file

@ -3,9 +3,11 @@
import argparse
import csv
import datetime
import json
import logging
import os
import queue
import shlex
import subprocess
import time
@ -501,13 +503,13 @@ class LegendaryCLI:
logger.info(f'Launch parameters: {shlex.join(params)}')
logger.info(f'Working directory: {cwd}')
if env:
logger.info('Environment overrides:', env)
logger.info(f'Environment overrides: {env}')
else:
logger.info(f'Launching {app_name}...')
logger.debug(f'Launch parameters: {shlex.join(params)}')
logger.debug(f'Working directory: {cwd}')
if env:
logger.debug('Environment overrides:', env)
logger.debug(f'Environment overrides: {env}')
subprocess.Popen(params, cwd=cwd, env=env)
def install_game(self, args):
@ -522,15 +524,15 @@ class LegendaryCLI:
logger.error(f'Update requested for "{args.app_name}", but app not installed!')
exit(1)
status_queue = MPQueue()
logger.info('Preparing download...')
# todo use status queue to print progress from CLI
# This has become a little ridiculous hasn't it?
try:
dlm, analysis, game, igame, repair, repair_file = self.core.prepare_download(
app_name=args.app_name,
base_path=args.base_path,
force=args.force,
no_install=args.no_install,
status_q=status_queue,
max_shm=args.shared_memory,
max_workers=args.max_workers,
game_folder=args.game_folder,
@ -578,6 +580,22 @@ class LegendaryCLI:
dlm.proc_debug = args.dlm_debug
dlm.start()
time.sleep(1)
while dlm.is_alive():
try:
status = status_queue.get(timeout=0.1)
logger.info(f'= Progress: {status.progress:.02f}% ({status.processed_chunks}/{status.chunk_tasks}), '
f'Running for {str(datetime.timedelta(seconds=status.runtime))}, '
f'ETA: {str(datetime.timedelta(seconds=status.estimated_time_left))}')
logger.info(f' - Downloaded: {status.total_downloaded / 1024 / 1024:.02f} MiB, '
f'Written: {status.total_written / 1024 / 1024:.02f} MiB')
logger.info(f' - Cache usage: {status.cache_usage} MiB, active tasks: {status.active_tasks}')
logger.info(f' + Download\t- {status.download_speed / 1024 / 1024:.02f} MiB/s (raw) '
f'/ {status.download_decompressed_speed / 1024 / 1024:.02f} MiB/s (decompressed)')
logger.info(f' + Disk\t- {status.write_speed / 1024 / 1024:.02f} MiB/s (write) / '
f'{status.read_speed / 1024 / 1024:.02f} MiB/s (read)')
except queue.Empty:
pass
dlm.join()
except Exception as e:
end_t = time.time()

View file

@ -24,8 +24,8 @@ from legendary.lfs.lgndry import LGDLFS
from legendary.utils.lfs import clean_filename, delete_folder, delete_filelist, validate_files
from legendary.models.downloading import AnalysisResult, ConditionCheckResult
from legendary.models.egl import EGLManifest
from legendary.models.exceptions import *
from legendary.models.game import *
from legendary.models.exceptions import InvalidCredentialsError
from legendary.models.game import GameAsset, Game, InstalledGame, SaveGameFile, SaveGameStatus, VerifyResult
from legendary.models.json_manifest import JSONManifest
from legendary.models.manifest import Manifest, ManifestMeta
from legendary.models.chunk import Chunk

View file

@ -695,35 +695,30 @@ class DLManager(Process):
total_avail = len(self.sms)
total_used = (num_shared_memory_segments - total_avail) * (self.analysis.biggest_chunk / 1024 / 1024)
if runtime and processed_chunks:
rt_hours, runtime = int(runtime // 3600), runtime % 3600
rt_minutes, rt_seconds = int(runtime // 60), int(runtime % 60)
try:
average_speed = processed_chunks / runtime
estimate = (num_chunk_tasks - processed_chunks) / average_speed
hours, estimate = int(estimate // 3600), estimate % 3600
minutes, seconds = int(estimate // 60), int(estimate % 60)
else:
hours = minutes = seconds = 0
rt_hours = rt_minutes = rt_seconds = 0
self.log.info(f'= Progress: {perc:.02f}% ({processed_chunks}/{num_chunk_tasks}), '
f'Running for {rt_hours:02d}:{rt_minutes:02d}:{rt_seconds:02d}, '
f'ETA: {hours:02d}:{minutes:02d}:{seconds:02d}')
self.log.info(f' - Downloaded: {total_dl / 1024 / 1024:.02f} MiB, '
f'Written: {total_write / 1024 / 1024:.02f} MiB')
self.log.info(f' - Cache usage: {total_used} MiB, active tasks: {self.active_tasks}')
self.log.info(f' + Download\t- {dl_speed / 1024 / 1024:.02f} MiB/s (raw) '
f'/ {dl_unc_speed / 1024 / 1024:.02f} MiB/s (decompressed)')
self.log.info(f' + Disk\t- {w_speed / 1024 / 1024:.02f} MiB/s (write) / '
f'{r_speed / 1024 / 1024:.02f} MiB/s (read)')
except ZeroDivisionError:
average_speed = estimate = 0
# TODO set current_filename argument of UIUpdate
# send status update to back to instantiator (if queue exists)
if self.status_queue:
try:
self.status_queue.put(UIUpdate(
progress=perc, download_speed=dl_unc_speed, write_speed=w_speed, read_speed=r_speed,
memory_usage=total_used * 1024 * 1024
progress=perc,
runtime=round(runtime),
estimated_time_left=round(estimate),
processed_chunks=processed_chunks,
chunk_tasks=num_chunk_tasks,
total_downloaded=total_dl,
total_written=total_write,
cache_usage=total_used,
active_tasks=self.active_tasks,
download_speed=dl_speed,
download_decompressed_speed=dl_unc_speed,
write_speed=w_speed,
read_speed=r_speed,
), timeout=1.0)
except Exception as e:
self.log.warning(f'Failed to send status update to queue: {e!r}')

View file

@ -70,14 +70,23 @@ class UIUpdate:
Status update object sent from the manager to the CLI/GUI to update status indicators
"""
def __init__(self, progress, download_speed, write_speed, read_speed,
memory_usage, current_filename=''):
def __init__(self, progress, runtime, estimated_time_left, processed_chunks, chunk_tasks,
total_downloaded, total_written, cache_usage, active_tasks, download_speed,
download_decompressed_speed, write_speed, read_speed, current_filename=''):
self.progress = progress
self.runtime = runtime
self.estimated_time_left = estimated_time_left
self.processed_chunks = processed_chunks
self.chunk_tasks = chunk_tasks
self.total_downloaded = total_downloaded
self.total_written = total_written
self.cache_usage = cache_usage
self.active_tasks = active_tasks
self.download_speed = download_speed
self.download_decompressed_speed = download_decompressed_speed
self.write_speed = write_speed
self.read_speed = read_speed
self.current_filename = current_filename
self.memory_usage = memory_usage
class SharedMemorySegment: