[SOLVED] Doubt: how to show the download status of a file? (Using "wget" module)

Discuss how to use the Ren'Py engine to create visual novels and story-based games. New releases are announced in this section.
Forum rules
This is the right place for Ren'Py help. Please ask one question per thread, use a descriptive subject like 'NotFound error in option.rpy' , and include all the relevant information - especially any relevant code and traceback messages. Use the code tag to format scripts.
Post Reply
Message
Author
User avatar
CharlieFuu69
Regular
Posts: 30
Joined: Mon Nov 11, 2019 10:32 pm
Projects: Current projects using Ren'Py : "Tears: The First Love!" (Visual Novel at 90%) , "ElectroBasics Electronic Quiz!" (Educative game at 45%).
Location: Chile
Contact:

[SOLVED] Doubt: how to show the download status of a file? (Using "wget" module)

#1 Post by CharlieFuu69 » Sat Oct 31, 2020 1:18 am

Hello guys.
I apologize if this rookie question causes annoyance to people, but I've been thinking about it for days.
A few days ago I discovered a Python module called "wget", which I want to use to create an in-game asset downloader. It is a fairly simple module to use and works perfect for downloading files.
This is the code I use to make it work in the Python interpreter:

Code: Select all

## "wget" module for download files
import wget

## Links and file output
Assets_Link = "The URL of the files"

print("Acquiring URL...")

## This function shows download status (Percent and bytes)
## Example : Downloading... 10% [0 / 1024] Bytes
def status_custom(current, total, width=80):
    print("Downloading... %d%% [%d / %d] Bytes" %(current / total * 100, current, total))

## MODULE IN ACTION [DOWNLOAD FILES]
try:
    update_download = wget.download(Assets_Link, bar=status_custom)
    update_received = True
except:
    update_received = False

if update_received:
    print("The game is Up-to-date! :D")

else:
    print("Oops. Something went wrong :(")
    
The status_custom function is responsible for showing the current status of the download (Percentage and bytes of the file), and displays each percentage line by line on the interpreter.

I have adapted the code into a ".rpy" script which works perfect except for one thing. I can't show the download indicator on the interface.
The code adapted to the Ren'Py environment is this:

Code: Select all

init python:
    import wget

## [UI] Download screen
screen Upd_Downloading():
    vbox at prompt_anim_2:
        text "Downloading..." style "Connecting_Data" xalign 0.5
        null height 25
        text "Getting game files..." style "Warning_Message_02" xalign 0.5
        text "Path : [persistent.File_Name]" style "Warning_Message_02" xalign 0.5
        text ## Show the download status here ##

## The game starts here
label start:
    show screen Upd_Downloading
    scene background_01 with dissolve
    python:
        Assets_Link = "The URL of the files"
        
        ## Function for show download status
        def status_custom(current, total, width=80):
            print("Downloading... %d%% [%d / %d] Bytes" %(current / total * 100, current, total))

        try:
            ## The download starts here
            update_download = wget.download(Assets_Link, bar=status_custom)
            update_received = True
        except:
            update_received = False
            
    ## Dialogue blocks
    if update_received:
        "The game is Up-to-date! :D"
    else:
        "Oops. Something went wrong :(\nTry again!"
        
the Upd_Downloading screen is displayed just before starting the download with the Python block. (Showing it after the python block wouldn't be too useful since that screen would show up after the download is done).

The idea is that this screen is able to show the current status of the download, at the moment that "wget" is doing its job.

MY TRIES:
I tried to make the function return the status of the download using Text() to create a DynamicDisplayable() and thus display it on the screen using add, but I had no success.
I tried stupidly to put inside the screen, a line with text and the name of the function. I was also unsuccessful.
If I put the status_customfunction in a init python block, or before the python block where the download takes place, I get an error of type ZeroDivisionError (The values it shows are divided by zero, so it throws an error).

Help me please :"(
Last edited by CharlieFuu69 on Sat Oct 31, 2020 6:42 pm, edited 1 time in total.

User avatar
gas
Miko-Class Veteran
Posts: 838
Joined: Mon Jan 26, 2009 7:21 pm
Contact:

Re: Doubt: how to show the download status of a file? (Using "wget" module)

#2 Post by gas » Sat Oct 31, 2020 2:44 pm

A: move that status_custom def to the top of the script and wrap it in an init python: statement instead.
That way the function will be created in advance and called just when needed (at this stage you should already own variables different than 0).

B: create a dynamic displayable AND ALSO a function that each frame go retrieve the wget status. You just need to show that like any other image, no need of a screen that could create interaction issues.

C: how you stop execution progress?

Wild guesses, I can't test right now, but they should work.
If you want to debate on a reply I gave to your posts, please QUOTE ME or i'll not be notified about. << now red so probably you'll see it.

10 ? "RENPY"
20 GOTO 10

RUN

User avatar
CharlieFuu69
Regular
Posts: 30
Joined: Mon Nov 11, 2019 10:32 pm
Projects: Current projects using Ren'Py : "Tears: The First Love!" (Visual Novel at 90%) , "ElectroBasics Electronic Quiz!" (Educative game at 45%).
Location: Chile
Contact:

Re: Doubt: how to show the download status of a file? (Using "wget" module)

#3 Post by CharlieFuu69 » Sat Oct 31, 2020 4:24 pm

Apparently everything was going to work fine, except for this problem ...

Code: Select all

I'm sorry, but an uncaught exception occurred.

While running game code:
  File "game/script.rpy", line 17, in script
    scene background_begin with dissolve
ValueError: too many values to unpack

-- Full Traceback ------------------------------------------------------------

Full traceback:
  File "game/script.rpy", line 17, in script
    scene background_begin with dissolve
  File "E:\@CharlieFuu69 OT-SUR\renpy-7.3.5-sdk\renpy\ast.py", line 1389, in execute
    renpy.exports.with_statement(trans, paired)
  File "E:\@CharlieFuu69 OT-SUR\renpy-7.3.5-sdk\renpy\exports.py", line 1601, in with_statement
    return renpy.game.interface.do_with(trans, paired, clear=clear)
  File "E:\@CharlieFuu69 OT-SUR\renpy-7.3.5-sdk\renpy\display\core.py", line 2251, in do_with
    clear=clear)
  File "E:\@CharlieFuu69 OT-SUR\renpy-7.3.5-sdk\renpy\display\core.py", line 2702, in interact
    repeat, rv = self.interact_core(preloads=preloads, trans_pause=trans_pause, **kwargs)
  File "E:\@CharlieFuu69 OT-SUR\renpy-7.3.5-sdk\renpy\display\core.py", line 3194, in interact_core
    self.draw_screen(root_widget, fullscreen_video, (not fullscreen_video) or video_frame_drawn)
  File "E:\@CharlieFuu69 OT-SUR\renpy-7.3.5-sdk\renpy\display\core.py", line 2094, in draw_screen
    renpy.config.screen_height,
  File "renpy/display/render.pyx", line 490, in renpy.display.render.render_screen (gen\renpy.display.render.c:6805)
    rv = render(root, width, height, st, st)
  File "renpy/display/render.pyx", line 259, in renpy.display.render.render (gen\renpy.display.render.c:3520)
    rv = d.render(widtho, heighto, st, at)
  File "E:\@CharlieFuu69 OT-SUR\renpy-7.3.5-sdk\renpy\display\layout.py", line 722, in render
    surf = render(child, width, height, cst, cat)
  File "renpy/display/render.pyx", line 166, in renpy.display.render.render (gen\renpy.display.render.c:4075)
    cpdef render(d, object widtho, object heighto, double st, double at):
  File "renpy/display/render.pyx", line 259, in renpy.display.render.render (gen\renpy.display.render.c:3520)
    rv = d.render(widtho, heighto, st, at)
  File "E:\@CharlieFuu69 OT-SUR\renpy-7.3.5-sdk\renpy\display\transition.py", line 361, in render
    top = render(self.new_widget, width, height, st, at)
  File "renpy/display/render.pyx", line 166, in renpy.display.render.render (gen\renpy.display.render.c:4075)
    cpdef render(d, object widtho, object heighto, double st, double at):
  File "renpy/display/render.pyx", line 259, in renpy.display.render.render (gen\renpy.display.render.c:3520)
    rv = d.render(widtho, heighto, st, at)
  File "E:\@CharlieFuu69 OT-SUR\renpy-7.3.5-sdk\renpy\display\layout.py", line 722, in render
    surf = render(child, width, height, cst, cat)
  File "renpy/display/render.pyx", line 166, in renpy.display.render.render (gen\renpy.display.render.c:4075)
    cpdef render(d, object widtho, object heighto, double st, double at):
  File "renpy/display/render.pyx", line 259, in renpy.display.render.render (gen\renpy.display.render.c:3520)
    rv = d.render(widtho, heighto, st, at)
  File "E:\@CharlieFuu69 OT-SUR\renpy-7.3.5-sdk\renpy\display\layout.py", line 722, in render
    surf = render(child, width, height, cst, cat)
  File "renpy/display/render.pyx", line 166, in renpy.display.render.render (gen\renpy.display.render.c:4075)
    cpdef render(d, object widtho, object heighto, double st, double at):
  File "renpy/display/render.pyx", line 259, in renpy.display.render.render (gen\renpy.display.render.c:3520)
    rv = d.render(widtho, heighto, st, at)
  File "E:\@CharlieFuu69 OT-SUR\renpy-7.3.5-sdk\renpy\display\screen.py", line 675, in render
    child = renpy.display.render.render(self.child, w, h, st, at)
  File "renpy/display/render.pyx", line 166, in renpy.display.render.render (gen\renpy.display.render.c:4075)
    cpdef render(d, object widtho, object heighto, double st, double at):
  File "renpy/display/render.pyx", line 259, in renpy.display.render.render (gen\renpy.display.render.c:3520)
    rv = d.render(widtho, heighto, st, at)
  File "E:\@CharlieFuu69 OT-SUR\renpy-7.3.5-sdk\renpy\display\layout.py", line 722, in render
    surf = render(child, width, height, cst, cat)
  File "renpy/display/render.pyx", line 166, in renpy.display.render.render (gen\renpy.display.render.c:4075)
    cpdef render(d, object widtho, object heighto, double st, double at):
  File "renpy/display/render.pyx", line 259, in renpy.display.render.render (gen\renpy.display.render.c:3520)
    rv = d.render(widtho, heighto, st, at)
  File "accelerator.pyx", line 110, in renpy.display.accelerator.transform_render
  File "renpy/display/render.pyx", line 259, in renpy.display.render.render (gen\renpy.display.render.c:3520)
    rv = d.render(widtho, heighto, st, at)
  File "E:\@CharlieFuu69 OT-SUR\renpy-7.3.5-sdk\renpy\display\layout.py", line 925, in render
    surf = render(d, width - x, rh, cst, cat)
  File "renpy/display/render.pyx", line 166, in renpy.display.render.render (gen\renpy.display.render.c:4075)
    cpdef render(d, object widtho, object heighto, double st, double at):
  File "renpy/display/render.pyx", line 259, in renpy.display.render.render (gen\renpy.display.render.c:3520)
    rv = d.render(widtho, heighto, st, at)
  File "accelerator.pyx", line 110, in renpy.display.accelerator.transform_render
  File "renpy/display/render.pyx", line 259, in renpy.display.render.render (gen\renpy.display.render.c:3520)
    rv = d.render(widtho, heighto, st, at)
  File "E:\@CharlieFuu69 OT-SUR\renpy-7.3.5-sdk\renpy\display\layout.py", line 1283, in render
    self.update(st, at)
  File "E:\@CharlieFuu69 OT-SUR\renpy-7.3.5-sdk\renpy\display\layout.py", line 1265, in update
    child, redraw = self.function(st, at, *self.args, **self.kwargs)
ValueError: too many values to unpack

Windows-8-6.2.9200
Ren'Py 7.3.5.606
File_Writer 1.0
Sat Oct 31 17:13:08 2020
when using it as an image it throws me the present error. I imagine it is because the code generates too many status updates and it cannot display them all at once.
How can I make it update itself, along the same line? In that case, how can I make the function return an iterable value?

User avatar
gas
Miko-Class Veteran
Posts: 838
Joined: Mon Jan 26, 2009 7:21 pm
Contact:

Re: Doubt: how to show the download status of a file? (Using "wget" module)

#4 Post by gas » Sat Oct 31, 2020 5:50 pm

Can you post the code so far?
Too many values to unpack means you're passing a list or dictionary when just one value is required by a method.
I dunno how wget internally work, but probably you're passing such type.
If you want to debate on a reply I gave to your posts, please QUOTE ME or i'll not be notified about. << now red so probably you'll see it.

10 ? "RENPY"
20 GOTO 10

RUN

User avatar
Vladya
Regular
Posts: 34
Joined: Sun Sep 20, 2020 3:16 am
Github: NyashniyVladya
Contact:

Re: Doubt: how to show the download status of a file? (Using "wget" module)

#5 Post by Vladya » Sat Oct 31, 2020 6:22 pm

I want to add that even if the code would work, without the implementation of logic using threads, the game will hang before the loading is over.

Sample working code with threading logic:

Code: Select all


init python:

    import threading
    import wget
    from os import path

    class DownloadControl(threading.Thread):

        def __init__(self, url, out=None):

            super(DownloadControl, self).__init__()
            self.daemon = True

            self.__url = url
            self.__out = out

            self.__download_status = None
            self.__is_finished = False

            self.__exception = None
            self.__result_filename = None

        @property
        def status(self):
            return (self.__download_status or .0)

        @property
        def _filename(self):
            return self.__result_filename

        def download_is_finished(self):
            return self.__is_finished

        def _has_exception(self):
            if isinstance(self.__exception, Exception):
                return True
            return False

        def _raise_from_thread(self):
            if self._has_exception():
                raise self.__exception

        def _callback_func(self, current, total, *args, **kwargs):
            current, total = map(float, (current, total))
            if total > .0:
                self.__download_status = (current / total)
                renpy.restart_interaction()

        def run(self):

            try:
                _result_fn = wget.download(
                    self.__url,
                    self.__out,
                    bar=self._callback_func
                )
            except Exception as ex:
                self.__exception = ex
                self.__download_status = .0
            else:
                self.__result_filename = path.abspath(_result_fn)
            finally:
                self.__is_finished = True
                renpy.restart_interaction()


screen download_screen(url, out=None):

    default download_thread = DownloadControl(url, out)
    default _download_is_started = False

    showif _download_is_started:
        showif download_thread.download_is_finished():
            showif download_thread._has_exception():
                vbox:
                    text "Error have occurred."
                    textbutton "Raise traceback." action Function(
                        download_thread._raise_from_thread
                    )
            else:
                vbox:
                    text "Download completed."
                    textbutton "Return" action Return()
        else:
            vbox:
                text "Download {0:.1%}.".format(download_thread.status)
                bar value AnimatedValue(download_thread.status, 1.)
    else:
        textbutton "Start download" action (
            Function(download_thread.start),
            SetScreenVariable("_download_is_started", True)
        )


label start:
    call screen download_screen("https://www.renpy.org/dl/7.3.5/renpy-7.3.5-sdk.7z.exe")
    return


User avatar
CharlieFuu69
Regular
Posts: 30
Joined: Mon Nov 11, 2019 10:32 pm
Projects: Current projects using Ren'Py : "Tears: The First Love!" (Visual Novel at 90%) , "ElectroBasics Electronic Quiz!" (Educative game at 45%).
Location: Chile
Contact:

Re: Doubt: how to show the download status of a file? (Using "wget" module)

#6 Post by CharlieFuu69 » Sat Oct 31, 2020 6:41 pm

>> Vladya
Great! I tested the code you have attached and it works perfect!
You were right that the game freezes when downloading, since in my case it freezes while getting the file through wget.
Since it has worked, I will study the operation of your code to understand and improve it :)
Thank you!!!

Post Reply

Who is online

Users browsing this forum: span4ev