pythonfilestreamopenstacksdk

python openstack SDK show file upload via progress bar


With the python openstack SDK, you can download an image, chunk by chunk, which allowed me to show a progress bar.

You can't seem to do the same when uploading a file.

What I want is to be able to show a progress bar of the file being uploaded (in the same way I have for the file being downloaded).

Is there a way to attach a kind of "file read" call back to the file object? so every time it get's read I can show a progress bar?

I did look at the python file object docs but I couldn't really find anything definitive.

P.s.

For those that are interested, my code:

ESCAPE = {
    'c': { # colours
        'fg': { # foreground
            'b': '30', # black
            'r': '31', # red
            'g': '32', # green
            'y': '33', # yellow
            'u': '34', # blue
            'p': '35', # purple
            'c': '36', # cyan
            'w': '37', # white
        },
        'bg': { # background
            'b': '40', # black
            'r': '41', # red
            'g': '42', # green
            'y': '43', # yellow
            'u': '44', # blue
            'p': '45', # purple
            'c': '46', # cyan
            'w': '47', # white
        }
    },
    's': { # style
        'n': '0',  # none
        'b': '1',  # bold
        'u': '2',  # underline
        'n1': '3', # negative1
        'n2': '5', # negative2
    },
    't': '\033[{s};{fg};{bg}m' # template 
}

def spinner(msg: str):
    template = f"{colour(fg='p', s='b')}{'{}'}{colour()} {msg}"
    while True:
        for spin in '⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏':
            yield template.format(spin)

def progress(end: int, max_col=78):
    template = f"[{colour(bg='g')}{'{}'}{colour(bg='r')}{'{}'}{colour()}|{'{}'}]"
    for p in range(1, end):
        bar = ' ' * int(max_col * p/(end-1))
        togo = ' ' * int(max_col - len(bar))
        perc = "%6.2f %%" % (p/(end-1)*100)
        yield template.format(bar, togo, perc)

def colour(fg='w', bg='b', s='n'):
    return ESCAPE['t'].format(
            s=ESCAPE['s'][s],
            fg=ESCAPE['c']['fg'][fg],
            bg=ESCAPE['c']['bg'][bg]
    )


Solution

  • So, after quite a bit of searching I was able to find a way to do what I was asking (here & here).

    code:

    #!/usr/bin/env python3
    from types import MethodType
    
    def hook(hookfunk, oldfunc):
        def merged(self, *args, **kwargs):
            hookfunk(self, *args, **kwargs)
            return oldfunc(*args, **kwargs)
        return  MethodType(merged, oldfunc.__self__)
    
    
    f = open('cirros.qcow2', 'rb')
    
    def new_read(self, size):
        print(self)
        # Or do other code, like updating a progress bar
    
    f.read = hook(new_read, f.read)
    
    f.read()