1

I'm trying to upload a file in thread. So later I can add callback with progress bar update etc.

I've tried to do that with threading and PySimpleGui's perform_long_operation. It is not working this way.

So how do I do it? Probably, I'm missing something about asyncio usage.

from pyrogram import Client
from time import sleep
import PySimpleGUI as sg
import asyncio
import random
import sys

api_id = 234242434
api_hash = '324423423'


sg.change_look_and_feel('DarkAmber')

layout = [
    [sg.Text('Password'), sg.InputText(password_char='*', key='password')],
    [sg.Text('', key='status', size=(20, 1))],
    [sg.Button('Submit'), sg.Button('Cancel')]
]

window = sg.Window('TG Send', layout, finalize=True)

client = None

def long_proc():
    client = Client('tg_send', api_id, api_hash)
    window['status'].update('connecting')
    client.connect()
    window['status'].update('started')

    done = False
    while True:
        if not done:
            print('Uploading file')
            window['status'].update('uploading')
            client.send_document('me', document='File.db')
            done = True
            print('Uploading done')
            window['status'].update('uploaded')
        else:
            sleep(1)
    

async def ui():
    while True:
        event, value = window.read(timeout=1)
        if event in (None, 'Cancel'):
            sys.exit()
        
        if event != '__TIMEOUT__':
            print(f"{event=} {value=}")
        
        if event == 'Submit':
            window.perform_long_operation(long_proc, '-FUNCTION COMPLETED-')

        await asyncio.sleep(0)


async def main():
    await asyncio.gather(
        asyncio.create_task(ui()),
        # asyncio.to_thread(long_proc),
        
    )
    

if __name__ == '__main__':
    asyncio.run(main())
Shivang Kakkar
  • 421
  • 3
  • 15
MonZon
  • 31
  • 9

1 Answers1

1

Following information is just for the code about PySimpleGUI and not about async and asyncio.

def long_proc():
    client = Client('tg_send', api_id, api_hash)
    window['status'].update('connecting')                   # Wrong call in thread
    client.connect()
    window['status'].update('started')                      # Wrong call in thread

    done = False
    while True:
        if not done:
            print('Uploading file')
            window['status'].update('uploading')            # Wrong call in thread
            client.send_document('me', document='File.db')
            done = True
            print('Uploading done')
            window['status'].update('uploaded')             # Wrong call in thread
        else:
            sleep(1)

perform_long_operation

This method uses THREADS. This means you CANNOT make any PySimpleGUI calls from the function you provide with the exception of one function, Window.write_event_value.

Instead, handle the event -STATUS- in your event loop by calling window['status'].update(values['-STATUS-']).

def long_proc():
    client = Client('tg_send', api_id, api_hash)
    window.write_event_value('-STATUS-', 'connecting')
    client.connect()
    window.write_event_value('-STATUS-', 'started')

    done = False
    while True:
        if not done:
            print('Uploading file')
            window.write_event_value('-STATUS-', 'uploading')
            client.send_document('me', document='File.db')
            done = True
            print('Uploading done')
            window.write_event_value('-STATUS-', 'uploaded')
        else:
            sleep(1)
Shivang Kakkar
  • 421
  • 3
  • 15
Jason Yang
  • 11,284
  • 2
  • 9
  • 23
  • Oh, my bad. Thanks for the hint. I've tried your code, now I'm getting '-STATUS-': 'connecting', but no 'updating' or 'uploaded'. No file gets uploaded to TG. I mentioned asyncio, because send_document(..) is defined as async def send_document(...). I assume I need some special way to run it from thread? I've been using it in non-async and non-thread functions the same way and it works fine. – MonZon Mar 06 '22 at 16:58