Rocksolid Light

Welcome to RetroBBS

mail  files  register  newsreader  groups  login

Message-ID:  

The devil finds work for idle circuits to do.


devel / comp.lang.python / Re: Using a background thread with asyncio/futures with flask

SubjectAuthor
* Re: Using a background thread with asyncio/futures with flaskThomas Nyberg
`- Re: Using a background thread with asyncio/futures with flaskMark Bourne

1
Re: Using a background thread with asyncio/futures with flask

<mailman.7.1711102151.3468.python-list@python.org>

  copy mid

https://www.rocksolidbbs.com/devel/article-flat.php?id=29715&group=comp.lang.python#29715

  copy link   Newsgroups: comp.lang.python
Path: i2pn2.org!i2pn.org!news.swapon.de!fu-berlin.de!uni-berlin.de!not-for-mail
From: twn@thomasnyberg.com (Thomas Nyberg)
Newsgroups: comp.lang.python
Subject: Re: Using a background thread with asyncio/futures with flask
Date: Fri, 22 Mar 2024 11:08:58 +0100
Lines: 237
Message-ID: <mailman.7.1711102151.3468.python-list@python.org>
References: <8a7231df-c30c-4fa6-9daa-546b3453b547@thomasnyberg.com>
<09efe843-195e-48c0-a9cb-6fe05e3a6921@solute.de>
<dcdef19d-cca1-4ce3-af8d-ae79abf79ec8@thomasnyberg.com>
Mime-Version: 1.0
Content-Type: text/plain; charset=UTF-8; format=flowed
Content-Transfer-Encoding: 8bit
X-Trace: news.uni-berlin.de JSOjBdikEKoQAym4ErecBAq+M+YlMKuGK6mmWz4uzNGQ==
Cancel-Lock: sha1:OaegFhYculCYuOqjVzrlPHUBdJY= sha256:5ZnDSk5Cn1i9X+Lqts/Jyxxil6U9a8gpjfPtNLH2DmA=
Return-Path: <twn@thomasnyberg.com>
X-Original-To: python-list@python.org
Delivered-To: python-list@mail.python.org
Authentication-Results: mail.python.org; dkim=pass
reason="2048-bit key; unprotected key"
header.d=thomasnyberg.com header.i=@thomasnyberg.com
header.b=xrZ4oO+s; dkim-adsp=pass; dkim-atps=neutral
X-Spam-Status: OK 0.001
X-Spam-Evidence: '*H*': 1.00; '*S*': 0.00; 'def': 0.04; 'debug': 0.07;
'e.g.': 0.07; 'loop': 0.07; 'queue': 0.07; 'serving': 0.07;
'python.': 0.08; 'debian': 0.09; 'freeze': 0.09; 'linux': 0.09;
'prints': 0.09; 'schrieb': 0.09; "shouldn't": 0.09; 'skip:[ 20':
0.09; 'threads': 0.09; 'url:de': 0.09; 'worker': 0.09; 'cheers,':
0.11; 'import': 0.15; 'that.': 0.15; '(after': 0.16; '(when':
0.16; '721': 0.16; 'brave': 0.16; 'cooperative': 0.16;
'deployment.': 0.16; 'easiest': 0.16; 'exhibits': 0.16; 'gmbh':
0.16; 'gnu/linux': 0.16; 'help!': 0.16; 'instead.': 0.16;
'presumably': 0.16; 'python3': 0.16; 'sees': 0.16; 'server,':
0.16; 'similar.': 0.16; 'sitz': 0.16; 'subject:thread': 0.16;
'threading': 0.16; 'warning:': 0.16; 'yield': 0.16; 'wrote:':
0.16; 'python': 0.16; 'developer': 0.16; 'uses': 0.19; 'server.':
0.19; 'to:addr:python-list': 0.20; 'written': 0.22; 'maybe': 0.22;
"what's": 0.22; 'version': 0.23; 'install': 0.23; 'installed':
0.23; 'run': 0.23; '(and': 0.25; 'register': 0.25; 'flask': 0.26;
'library': 0.26; "isn't": 0.27; 'old': 0.27; 'background': 0.28;
'printed': 0.28; 'wrong': 0.28; 'environment': 0.29; 'header:User-
Agent:1': 0.30; 'seem': 0.31; 'approach': 0.31; "doesn't": 0.32;
'do.': 0.32; 'happening': 0.32; 'python-list': 0.32;
'subject:Using': 0.32; 'but': 0.32; "i'm": 0.33;
'received:192.168.0': 0.33; 'server': 0.33; 'someone': 0.34;
'same': 0.34; 'printing': 0.34; 'header:In-Reply-To:1': 0.34;
'running': 0.34; 'trying': 0.35; 'following': 0.35; 'functions':
0.36; 'received:52': 0.37; 'main': 0.37; 'using': 0.37;
'received:192.168': 0.37; 'way': 0.38; 'put': 0.38; 'thanks':
0.38; 'use': 0.39; 'still': 0.40; 'learn': 0.40; 'something':
0.40; 'hello,': 0.40; 'want': 0.40; 'here.': 0.61; 'skip:o 10':
0.61; 'skip:i 20': 0.62; 'policy': 0.62; 'germany': 0.62; 'skip:z
10': 0.62; 'skip:o 20': 0.63; 'feel': 0.63; 'skip:b 10': 0.63;
'skip:t 40': 0.64; 'privacy': 0.64; 'well': 0.65; 'lead': 0.67;
'skip:t 30': 0.67; 'away': 0.67; 'amtsgericht': 0.69; 'await':
0.69; 'obvious': 0.69; 'playing': 0.69; 'url-ip:134/8': 0.69;
'workers': 0.69; 'url-ip:lookup error': 0.70; 'skip:a 40': 0.70;
'production': 0.71; 'skip:f 30': 0.71; 'virtual': 0.71; 'future':
0.72; 'url:php': 0.75; 'cheers': 0.76; 'dr.': 0.77; 'out,': 0.78;
'points': 0.84; 'asyncio.': 0.84; 'court:': 0.84; 'true:': 0.84;
'url:localhost': 0.84;
'\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0': 0.84
DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=thomasnyberg.com;
s=default; t=1711102142;
bh=gyKG51yrGRtpmwVj7XkKeIEJS9cQzUIBPvo5R5SBOSs=;
h=Date:Subject:To:References:From:In-Reply-To:From;
b=xrZ4oO+sNuvM+duRZNRwjSiCP6Cnin+I43d1Ztv/+zIN7jwBOHxGAuqJBwnx/lDSw
8xN5DMR+qabQMGIWn40EBMzcLsZUllOKryfYkI5rNd01KdsgD1VrUoGAgvy9TyK9VV
FJIwwtauY2jYlcxQ92074vz6qNlU2ijULS/Yxc6wZEwPh60eGlhXtEdah6M+/WGJ+V
3lhAI3bXoaSzQCEPAzTREdDZoA4MDpBoDoqE0g47U39A+xu8Iv+JX35oOpxtV17+N4
xB770TILbFy8dWuXLujQ3YReAC6E9elvHAo05k+ASJl89gYYa1rJj6XZp/NN+aE32H
A6iUH0VaBScIg==
User-Agent: Mozilla Thunderbird
Content-Language: en-US
In-Reply-To: <09efe843-195e-48c0-a9cb-6fe05e3a6921@solute.de>
X-BeenThere: python-list@python.org
X-Mailman-Version: 2.1.39
Precedence: list
List-Id: General discussion list for the Python programming language
<python-list.python.org>
List-Unsubscribe: <https://mail.python.org/mailman/options/python-list>,
<mailto:python-list-request@python.org?subject=unsubscribe>
List-Archive: <https://mail.python.org/pipermail/python-list/>
List-Post: <mailto:python-list@python.org>
List-Help: <mailto:python-list-request@python.org?subject=help>
List-Subscribe: <https://mail.python.org/mailman/listinfo/python-list>,
<mailto:python-list-request@python.org?subject=subscribe>
X-Mailman-Original-Message-ID: <dcdef19d-cca1-4ce3-af8d-ae79abf79ec8@thomasnyberg.com>
X-Mailman-Original-References: <8a7231df-c30c-4fa6-9daa-546b3453b547@thomasnyberg.com>
<09efe843-195e-48c0-a9cb-6fe05e3a6921@solute.de>
 by: Thomas Nyberg - Fri, 22 Mar 2024 10:08 UTC

Hi,

Yeah so flask does support async (when installed with `pip3 install
flask[async]), but you are making a good point that flask in this case
is a distraction. Here's an example using just the standard library that
exhibits the same issue:

`app.py`
```
import asyncio
import threading
import time
from queue import Queue

in_queue = Queue()
out_queue = Queue()

def worker():
print("worker started running")
while True:
future = in_queue.get()
print(f"worker got future: {future}")
time.sleep(5)
print("worker sleeped")
out_queue.put(future)

def finalizer():
print("finalizer started running")
while True:
future = out_queue.get()
print(f"finalizer got future: {future}")
future.set_result("completed")
print("finalizer set result")

threading.Thread(target=worker).start()
threading.Thread(target=finalizer).start()

async def main():
future = asyncio.get_event_loop().create_future()
in_queue.put(future)
print(f"main put future: {future}")
result = await future
print(result)

if __name__ == "__main__":
loop = asyncio.get_event_loop()
loop.run_until_complete(main())
```

If I run that I see the following printed out (after which is just hangs):

```
$ python3 app.py
worker started running
finalizer started running
main put future: <Future pending>
worker got future: <Future pending>
worker sleeped
finalizer got future: <Future pending cb=[Task.task_wakeup()]>
finalizer set result
```

I believe async uses a cooperative multitasking setup under the hood, so
I presume the way I'm doing this threading just isn't playing well with
that (and presumably some csp yield isn't happening somewhere). Anyway
at this point I feel like the easiest approach is to just throw away
threads entirely and learn how to do all I want fully in the brave new
async world, but I'm still curious why this is failing and how to make
this sort of setup work since it points to my not understanding the
basic implementation/semantics of async in python.

Thanks for any help!

/Thomas

On 3/22/24 08:27, Lars Liedtke via Python-list wrote:
> Hey,
>
> As far as I know (might be old news) flask does not support asyncio.
>
> You would have to use a different framework, like e.g. FastAPI or
> similar. Maybe someone has already written "flask with asyncio" but I
> don't know about that.
>
> Cheers
>
> Lars
>
>
> Lars Liedtke
> Lead Developer
>
> [Tel.]  +49 721 98993-
> [Fax]   +49 721 98993-
> [E-Mail]        lal@solute.de<mailto:lal@solute.de>
>
>
> solute GmbH
> Zeppelinstraße 15
> 76185 Karlsruhe
> Germany
>
> [Marken]
>
> Geschäftsführer | Managing Director: Dr. Thilo Gans, Bernd Vermaaten
> Webseite | www.solute.de <http://www.solute.de/>
> Sitz | Registered Office: Karlsruhe
> Registergericht | Register Court: Amtsgericht Mannheim
> Registernummer | Register No.: HRB 748044
> USt-ID | VAT ID: DE234663798
>
>
>
> Informationen zum Datenschutz | Information about privacy policy
> https://www.solute.de/ger/datenschutz/grundsaetze-der-datenverarbeitung.php
>
>
>
>
> Am 20.03.24 um 09:22 schrieb Thomas Nyberg via Python-list:
>
> Hello,
>
> I have a simple (and not working) example of what I'm trying to do. This
> is a simplified version of what I'm trying to achieve (obviously the
> background workers and finalizer functions will do more later):
>
> `app.py`
>
> ```
> import asyncio
> import threading
> import time
> from queue import Queue
>
> from flask import Flask
>
> in_queue = Queue()
> out_queue = Queue()
>
>
> def worker():
>    print("worker started running")
>    while True:
>        future = in_queue.get()
>        print(f"worker got future: {future}")
>        time.sleep(5)
>        print("worker sleeped")
>        out_queue.put(future)
>
>
> def finalizer():
>    print("finalizer started running")
>    while True:
>        future = out_queue.get()
>        print(f"finalizer got future: {future}")
>        future.set_result("completed")
>        print("finalizer set result")
>
>
> threading.Thread(target=worker, daemon=True).start()
> threading.Thread(target=finalizer, daemon=True).start()
>
> app = Flask(__name__)
>
>
> @app.route("/")
> async def root():
>    future = asyncio.get_event_loop().create_future()
>    in_queue.put(future)
>    print(f"root put future: {future}")
>    result = await future
>    return result
>
>
> if __name__ == "__main__":
>    app.run()
> ```
>
> If I start up that server, and execute `curl http://localhost:5000`, it
> prints out the following in the server before hanging:
>
> ```
> $ python3 app.py
> worker started running
> finalizer started running
> * Serving Flask app 'app'
> * Debug mode: off
> WARNING: This is a development server. Do not use it in a production
> deployment. Use a production WSGI server instead.
> * Running on http://127.0.0.1:5000
> Press CTRL+C to quit
> root put future: <Future pending>
> worker got future: <Future pending cb=[Task.task_wakeup()]>
> worker sleeped
> finalizer got future: <Future pending cb=[Task.task_wakeup()]>
> finalizer set result
> ```
>
> Judging by what's printing out, the `final result = await future`
> doesn't seem to be happy here.
>
> Maybe someone sees something obvious I'm doing wrong here? I presume I'm
> mixing threads and asyncio in a way I shouldn't be.
>
> Here's some system information (just freshly installed with pip3 install
> flask[async] in a virtual environment for python version 3.11.2):
>
> ```
> $ uname -a
> Linux x1carbon 6.1.0-18-amd64 #1 SMP PREEMPT_DYNAMIC Debian 6.1.76-1
> (2024-02-01) x86_64 GNU/Linux
>
> $ python3 -V
> Python 3.11.2
>
> $ pip3 freeze
> asgiref==3.7.2
> blinker==1.7.0
> click==8.1.7
> Flask==3.0.2
> itsdangerous==2.1.2
> Jinja2==3.1.3
> MarkupSafe==2.1.5
> Werkzeug==3.0.1
> ```
>
> Thanks for any help!
>
> Cheers,
> Thomas

Re: Using a background thread with asyncio/futures with flask

<utkrdo$353d7$1@dont-email.me>

  copy mid

https://www.rocksolidbbs.com/devel/article-flat.php?id=29727&group=comp.lang.python#29727

  copy link   Newsgroups: comp.lang.python
Path: i2pn2.org!i2pn.org!eternal-september.org!feeder3.eternal-september.org!news.eternal-september.org!.POSTED!not-for-mail
From: nntp.mbourne@spamgourmet.com (Mark Bourne)
Newsgroups: comp.lang.python
Subject: Re: Using a background thread with asyncio/futures with flask
Date: Fri, 22 Mar 2024 20:58:31 +0000
Organization: A noiseless patient Spider
Lines: 283
Message-ID: <utkrdo$353d7$1@dont-email.me>
References: <8a7231df-c30c-4fa6-9daa-546b3453b547@thomasnyberg.com>
<09efe843-195e-48c0-a9cb-6fe05e3a6921@solute.de>
<dcdef19d-cca1-4ce3-af8d-ae79abf79ec8@thomasnyberg.com>
<mailman.7.1711102151.3468.python-list@python.org>
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8; format=flowed
Content-Transfer-Encoding: 8bit
Injection-Date: Fri, 22 Mar 2024 20:58:32 -0000 (UTC)
Injection-Info: dont-email.me; posting-host="d74c01ed1b2a5c2a9bfba23aca4f99c0";
logging-data="3313063"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX1/mU73+JI2frv3h7vu1weu7"
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:91.0) Gecko/20100101
SeaMonkey/2.53.18.1
Cancel-Lock: sha1:vq9bQYnD9cjW5iuKjbtUqdG8HeY=
In-Reply-To: <mailman.7.1711102151.3468.python-list@python.org>
 by: Mark Bourne - Fri, 22 Mar 2024 20:58 UTC

Thomas Nyberg wrote:
> Hi,
>
> Yeah so flask does support async (when installed with `pip3 install
> flask[async]), but you are making a good point that flask in this case
> is a distraction. Here's an example using just the standard library that
> exhibits the same issue:
>
> `app.py`
> ```
> import asyncio
> import threading
> import time
> from queue import Queue
>
>
> in_queue = Queue()
> out_queue = Queue()
>
>
> def worker():
>     print("worker started running")
>     while True:
>         future = in_queue.get()
>         print(f"worker got future: {future}")
>         time.sleep(5)
>         print("worker sleeped")
>         out_queue.put(future)
>
>
> def finalizer():
>     print("finalizer started running")
>     while True:
>         future = out_queue.get()
>         print(f"finalizer got future: {future}")
>         future.set_result("completed")
>         print("finalizer set result")
>
>
> threading.Thread(target=worker).start()
> threading.Thread(target=finalizer).start()
>
>
> async def main():
>     future = asyncio.get_event_loop().create_future()
>     in_queue.put(future)
>     print(f"main put future: {future}")
>     result = await future
>     print(result)
>
>
> if __name__ == "__main__":
>     loop = asyncio.get_event_loop()
>     loop.run_until_complete(main())
> ```
>
> If I run that I see the following printed out (after which is just hangs):
>
> ```
> $ python3 app.py
> worker started running
> finalizer started running
> main put future: <Future pending>
> worker got future: <Future pending>
> worker sleeped
> finalizer got future: <Future pending cb=[Task.task_wakeup()]>
> finalizer set result
> ```
>
> I believe async uses a cooperative multitasking setup under the hood, so
> I presume the way I'm doing this threading just isn't playing well with
> that (and presumably some csp yield isn't happening somewhere). Anyway
> at this point I feel like the easiest approach is to just throw away
> threads entirely and learn how to do all I want fully in the brave new
> async world, but I'm still curious why this is failing and how to make
> this sort of setup work since it points to my not understanding the
> basic implementation/semantics of async in python.
>
> Thanks for any help!
>
> /Thomas
>
> On 3/22/24 08:27, Lars Liedtke via Python-list wrote:
>> Hey,
>>
>> As far as I know (might be old news) flask does not support asyncio.
>>
>> You would have to use a different framework, like e.g. FastAPI or
>> similar. Maybe someone has already written "flask with asyncio" but I
>> don't know about that.
>>
>> Cheers
>>
>> Lars
>>
>>
>> Lars Liedtke
>> Lead Developer
>>
>> [Tel.]  +49 721 98993-
>> [Fax]   +49 721 98993-
>> [E-Mail]        lal@solute.de<mailto:lal@solute.de>
>>
>>
>> solute GmbH
>> Zeppelinstraße 15
>> 76185 Karlsruhe
>> Germany
>>
>> [Marken]
>>
>> Geschäftsführer | Managing Director: Dr. Thilo Gans, Bernd Vermaaten
>> Webseite | www.solute.de <http://www.solute.de/>
>> Sitz | Registered Office: Karlsruhe
>> Registergericht | Register Court: Amtsgericht Mannheim
>> Registernummer | Register No.: HRB 748044
>> USt-ID | VAT ID: DE234663798
>>
>>
>>
>> Informationen zum Datenschutz | Information about privacy policy
>> https://www.solute.de/ger/datenschutz/grundsaetze-der-datenverarbeitung.php
>>
>>
>>
>>
>>
>> Am 20.03.24 um 09:22 schrieb Thomas Nyberg via Python-list:
>>
>> Hello,
>>
>> I have a simple (and not working) example of what I'm trying to do.
>> This is a simplified version of what I'm trying to achieve (obviously
>> the background workers and finalizer functions will do more later):
>>
>> `app.py`
>>
>> ```
>> import asyncio
>> import threading
>> import time
>> from queue import Queue
>>
>> from flask import Flask
>>
>> in_queue = Queue()
>> out_queue = Queue()
>>
>>
>> def worker():
>>     print("worker started running")
>>     while True:
>>         future = in_queue.get()
>>         print(f"worker got future: {future}")
>>         time.sleep(5)
>>         print("worker sleeped")
>>         out_queue.put(future)
>>
>>
>> def finalizer():
>>     print("finalizer started running")
>>     while True:
>>         future = out_queue.get()
>>         print(f"finalizer got future: {future}")
>>         future.set_result("completed")
>>         print("finalizer set result")
>>
>>
>> threading.Thread(target=worker, daemon=True).start()
>> threading.Thread(target=finalizer, daemon=True).start()
>>
>> app = Flask(__name__)
>>
>>
>> @app.route("/")
>> async def root():
>>     future = asyncio.get_event_loop().create_future()
>>     in_queue.put(future)
>>     print(f"root put future: {future}")
>>     result = await future
>>     return result
>>
>>
>> if __name__ == "__main__":
>>     app.run()
>> ```
>>
>> If I start up that server, and execute `curl http://localhost:5000`,
>> it prints out the following in the server before hanging:
>>
>> ```
>> $ python3 app.py
>> worker started running
>> finalizer started running
>> * Serving Flask app 'app'
>> * Debug mode: off
>> WARNING: This is a development server. Do not use it in a production
>> deployment. Use a production WSGI server instead.
>> * Running on http://127.0.0.1:5000
>> Press CTRL+C to quit
>> root put future: <Future pending>
>> worker got future: <Future pending cb=[Task.task_wakeup()]>
>> worker sleeped
>> finalizer got future: <Future pending cb=[Task.task_wakeup()]>
>> finalizer set result
>> ```
>>
>> Judging by what's printing out, the `final result = await future`
>> doesn't seem to be happy here.
>>
>> Maybe someone sees something obvious I'm doing wrong here? I presume
>> I'm mixing threads and asyncio in a way I shouldn't be.

Aside from possible issues mixing threads and asyncio (I'm no expert on
asyncio), there's also the issue that there's nothing to cause the
threads to exit. The following doesn't use asyncio, but also hangs
after the main thread has got the result:

```
import queue
import threading
import time

in_queue = queue.Queue()
out_queue = queue.Queue()
result_queue = queue.Queue()

def worker():
print("worker started running")
while True:
item = in_queue.get()
print(f"worker got item: {item}")
time.sleep(5)
print("worker sleeped")
out_queue.put(item)

def finalizer():
print("finalizer started running")
while True:
item = out_queue.get()
print(f"finalizer got item: {item}")
result_queue.put(item)
print("finalizer set result")

threading.Thread(target=worker).start()
threading.Thread(target=finalizer).start()
# threading.Thread(target=worker, daemon=True).start()
# threading.Thread(target=finalizer, daemon=True).start()

def main():
item = "Item to process"
in_queue.put("Item to process")
print(f"main put item: {item}")
result = None
while True:
try:
result = result_queue.get(timeout=1)
except queue.Empty:
# No result yet
print("main waiting for result")
continue
break
print(f"main got result {result}")


Click here to read the complete article
1
server_pubkey.txt

rocksolid light 0.9.8
clearnet tor