How to launch an async function to prevent app from freezing while doing long operations?

I have this functions and I need to call do_publish asynchronously, because of calculating nonce taking too much time:

async def verify_nonce(result, target):
    if len(result) != len(target):
        return False

    for i in range(len(result)):
        if result[i] > target[i]:
            return False
        elif result[i] < target[i]:
            break

    return True

async def solve_challenge(prefix, target_hex):
    target = unhexlify(target_hex.upper())
    nonce = 0

    while True:
        input_data = f"{prefix}{nonce}".encode()
        hashed = hashlib.sha256(input_data).digest()

        if await verify_nonce(hashed, target):
            break
        else:
            nonce += 1

    return str(nonce)

async def do_publish(*args):
    challenge_data = requests.post(url="https://lrclib.net/api/request-challenge")
    challenge_data_json = challenge_data.json()
    nonce = await solve_challenge(prefix=challenge_data_json['prefix'], target_hex=challenge_data_json['target'])
    print(f"X-Publish-Token: {challenge_data_json['prefix']}:{nonce}")
    #album = eyed3.load(main.app.win.filepath).tag.album
    response = requests.post(
        url="https://lrclib.net/api/publish",
        headers={"X-Publish-Token": f"{challenge_data_json['prefix']}:{nonce}", "Content-Type": "application/json"},
        params={'keep_headers': 'true'},
        json={
            "trackName": main.app.win.title,
            "artistName": main.app.win.artist,
            "albumName": eyed3.load(main.app.win.filepath).tag.album,
            "duration": int(eyed3.load(main.app.win.filepath).info.time_secs),
            "plainLyrics": prepare_plain_lyrics(),
            "syncedLyrics": prepare_synced_lyrics()
        }
    )
    print(response.status_code)

How can I do that?

Async support in PyGObect is new and experimental (since version 3.50).

We don’t have documentation for it yet, so you can take a look at some apps porting to use it:

But since you don’t seem to be using any async library (like aiohttp to make the request) you could just use Python threading to avoid blocking the UI. Here you can find more info: Threads & Concurrency - PyGObject.

2 Likes

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.