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

2024-03-22 Thread Mark Bourne via Python-list

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: 
worker got future: 
worker sleeped
finalizer got future: 
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]    l...@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 
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: 
worker got future: 
worker sleeped
finalizer got future: 
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 

Re: the name ``wheel''

2024-03-22 Thread Mats Wichmann via Python-list

On 3/22/24 11:45, Barry via Python-list wrote:




On 22 Mar 2024, at 15:25, Gilmeh Serda via Python-list  
wrote:


Many if not most Linux distributions do not include pip by default.


Really? It came with Manjaro.


Debian and Ubuntu require you to install pip as a separate package.
Also puts venv in its own package.

Fedora leaves all the batteries intact and rhel I assume.


pip is still a separate package in the .rpm world. which makes sense on 
a couple of levels:


* pip releases on its own cycle, you wouldn't want to have to *force* a 
new release of python + python-libs + python-devel + maybe others, if 
you happened want to rev pip forward independently.


* in a distro-packaged world, that's the primary place you get your 
Python packages from, and pip isn't seen as being as necessary, and 
potentially even as destructive. How many times have you seen an article 
that suggests you "sudo pip install randompackage"? Many distro setups 
now disallow installing like that. If you know what you're doing, and 
particularly if you're happy to control a specific environment by 
setting up a virtualenv, then fine, you'll still have access to 
everything you need.


anyway, I seem to recall the original message (which I've since deleted) 
was asking about Windows anyway.  There it's quite unusual to end up 
without pip, but not so unusual to end up without the *command* named 
pip - search path things, and all that. Usually if you "py -m pip 
--version" you'll see it's actually installed, just not accessible using 
the current search path.




--
https://mail.python.org/mailman/listinfo/python-list


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

2024-03-22 Thread Dieter Maurer via Python-list
dieter.mau...@online.de wrote at 2024-3-22 18:28 +0100:
>Thomas Nyberg wrote at 2024-3-22 11:08 +0100:
>> ... `future` use across thread boundaries ...
>> Here's an example using just the standard library that
>> exhibits the same issue:
> ...
>For use across thread boundaries, you likely will use
>`concurrent.Future` (not `asyncio.Future`).
>You can use `asyncio.futures._chain_futures` to associate
>an `asyncio.Future` with a `concurrent.Future`.
>Then the fate (result or exception set) of one will be reflected in the other.

You must not set the result/exception for a future in a "foreign" thread
("foreign" here means one not associated with the future's loop).
An aternative to the solution sketched above is to set the result
indirectly via `loop.call_soon_threadsafe`. This way, the
result is set in the futures "native" thread.
-- 
https://mail.python.org/mailman/listinfo/python-list


RE: Popping key causes dict derived from object to revert to object

2024-03-22 Thread AVI GROSS via Python-list
Loris wrote:

"Yes, I was mistakenly thinking that the popping the element would leave
me with the dict minus the popped key-value pair.  Seem like there is no
such function."

Others have tried to explain and pointed out you can del and then use the
changed dict.

But consider the odd concept of writing your own trivial function.

def remaining(adict, anitem):
  _ = adict.pop(anitem)
  # alternatively duse del on dict and item
  return adict


>>> remaining({"first": 1, "second": 2, "third": 3}, "second")
{'first': 1, 'third': 3}


Or do you want to be able to call it as in dict.remaining(key) by
subclassing your own variant of dict and adding a similar method?



-- 
https://mail.python.org/mailman/listinfo/python-list


Re: the name ``wheel''

2024-03-22 Thread Barry via Python-list


> On 22 Mar 2024, at 15:25, Gilmeh Serda via Python-list 
>  wrote:
> 
>> Many if not most Linux distributions do not include pip by default.
> 
> Really? It came with Manjaro.

Debian and Ubuntu require you to install pip as a separate package.
Also puts venv in its own package.

Fedora leaves all the batteries intact and rhel I assume.

Barry





-- 
https://mail.python.org/mailman/listinfo/python-list


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

2024-03-22 Thread Dieter Maurer via Python-list
Thomas Nyberg wrote at 2024-3-22 11:08 +0100:
> ... `future` use across thread boundaries ...
> Here's an example using just the standard library that
> exhibits the same issue:

I think all `asyncio` objects (futures, tasks, ...)
are meant to be used in a single thread.
If you use them across different threads, you must do special things.

Note that an `await(future)` registers a callback at *future*.
When the future gets its result or exception, the registered callback calls
are scheduled via `self._loop.call_soon`.
`call_soon` must be called from the `asyncio` thread (to which `self._loop`
belongs). A different thread may schedule activities for a loop
but it must use `call_soon_threadsafe` (not `call_soon`).

I would expect that the forbidden `call_soon` call raises an exception
which for reasons I do not know appears to be hidden.


For use across thread boundaries, you likely will use
`concurrent.Future` (not `asyncio.Future`).
You can use `asyncio.futures._chain_futures` to associate
an `asyncio.Future` with a `concurrent.Future`.
Then the fate (result or exception set) of one will be reflected in the other.
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Popping key causes dict derived from object to revert to object

2024-03-22 Thread Grant Edwards via Python-list
On 2024-03-22, Loris Bennett via Python-list  wrote:

> Yes, I was mistakenly thinking that the popping the element would
> leave me with the dict minus the popped key-value pair.

It does.

> Seem like there is no such function.

Yes, there is. You can do that with either pop or del:

>>> d = {'a':1, 'b':2, 'c':3}
>>> d
{'a': 1, 'b': 2, 'c': 3}
>>> d.pop('b')
2
>>> d
{'a': 1, 'c': 3}


>>> d = {'a':1, 'b':2, 'c':3}
>>> del d['b']
>>> d
{'a': 1, 'c': 3}

In both cases, you're left with the dict minus the key/value pair.

In the first case, the deleted value printed by the REPL because it
was returned by the expression "d.pop('b')" (a method call).

In the second case is no value shown by the REPL because "del d['b']"
is a statement not an expression.




-- 
https://mail.python.org/mailman/listinfo/python-list


Re: the name ``wheel''

2024-03-22 Thread Thomas Schweikle via Python-list



Am Do., 21.März.2024 um 18:58:26 schrieb Johanne Fairchild via Python-list:

r...@zedat.fu-berlin.de (Stefan Ram) writes:


Johanne Fairchild  wrote or quoted:

Why is a whl-package called a ``wheel''?  Is it just a pronunciation for
the extension WHL or is it really a name?


   PyPi in its initial state was named "cheese shop", as the famous
   part in the show "Monty Python Cheese Shop". Because initially it
   only hosted links to the packages, so it was empty like that shop.
   And within a cheese shop what do you store? Wheels of cheese.


Lol!  Loved it.  (Thanks very much.)


Also, it seems that when I install Python on Windows, it doesn't come
with pip ready to run.  I had to say


   Some Python distributions do not come with pip pre-installed
   because they have their own package management systems.


But this was a Windows install.  I don't think Windows has its own
package management for Python packages.  I'd be totally surprised.


The python packages found at https://www.python.org/downloads/ come with 
pip and pip installed out of the box.


But there are others like active python having other packet managers 
they do not install pip out of the box. Refer to their instructions how 
to install packages.

--
Thomas



OpenPGP_signature.asc
Description: OpenPGP digital signature
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Popping key causes dict derived from object to revert to object

2024-03-22 Thread Loris Bennett via Python-list
Mark Bourne  writes:

> Loris Bennett wrote:
>> Hi,
>> I am using SQLAlchemy to extract some rows from a table of 'events'.
>>  From the call to the DB I get a list of objects of the type
>>sqlalchemy.orm.state.InstanceState
>> I would like to print these rows to the terminal using the
>> 'tabulate'
>> package, the documentation for which says
>>The module provides just one function, tabulate, which takes a
>> list of
>>lists or another tabular data type as the first argument, and outputs
>>a nicely formatted plain-text table
>> So as I understand it, I need to convert the InstanceState-objects
>> to,
>> say, dicts, in order to print them.  However I also want to remove one
>> of the keys from the output and assumed I could just pop it off each
>> event dict, thus:
>>event_dicts = [vars(e) for e in events]
>>  print(type(event_dicts[0]))
>>  event_dicts = [e.pop('_sa_instance_state', None) for e in event_dicts]
>>  print(type(event_dicts[0]))
>
> vars() returns the __dict__ attribute of the object.  It may not be a
> good idea to modify that dictionary directly (it will also affect the
> object), although it might be OK if you're not going to do anything
> else with the original objects.  To be safer, you could copy the event
> objects:
> event_dicts = [dict(vars(e)) for e in events]
> or:
> event_dicts = [vars(e).copy()]

Thanks for making this clear to me.  However, in the end I actually
decided to use the list comprehension without either 'dict()' or
'vars().  Instead I just select the keys I want and so don't need to pop
the unwanted key later and can simultaneously tweak the names of the
key for better printing to the terminal.

>> However, this prints
>>
>>
>> If I comment out the third line, which pops the unwanted key, I get
>>
>>
>> Why does popping one of the keys cause the elements of the list to
>> revert back to their original class?
>
> As Dieter pointed out, the main problem here is that pop() returns the
> value removed, not the dictionary with the rest of the values.  You
> probably want something more like:
> for e in event_dicts:
> del e['_sa_instance_state']
> (There's not really any point popping the value if you're not going to
> do anything with it - just delete the key from the dictionary)

Yes, I was mistakenly thinking that the popping the element would leave
me with the dict minus the popped key-value pair.  Seem like there is no
such function.

Cheers,

Loris
 
-- 
This signature is currently under constuction.
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Popping key causes dict derived from object to revert to object

2024-03-22 Thread Mark Bourne via Python-list

Loris Bennett wrote:

Hi,

I am using SQLAlchemy to extract some rows from a table of 'events'.
 From the call to the DB I get a list of objects of the type

   sqlalchemy.orm.state.InstanceState

I would like to print these rows to the terminal using the 'tabulate'
package, the documentation for which says

   The module provides just one function, tabulate, which takes a list of
   lists or another tabular data type as the first argument, and outputs
   a nicely formatted plain-text table

So as I understand it, I need to convert the InstanceState-objects to,
say, dicts, in order to print them.  However I also want to remove one
of the keys from the output and assumed I could just pop it off each
event dict, thus:
  
 event_dicts = [vars(e) for e in events]

 print(type(event_dicts[0]))
 event_dicts = [e.pop('_sa_instance_state', None) for e in event_dicts]
 print(type(event_dicts[0]))


vars() returns the __dict__ attribute of the object.  It may not be a 
good idea to modify that dictionary directly (it will also affect the 
object), although it might be OK if you're not going to do anything else 
with the original objects.  To be safer, you could copy the event objects:

event_dicts = [dict(vars(e)) for e in events]
or:
event_dicts = [vars(e).copy()]


However, this prints

   
   

If I comment out the third line, which pops the unwanted key, I get

   
   

Why does popping one of the keys cause the elements of the list to
revert back to their original class?


As Dieter pointed out, the main problem here is that pop() returns the 
value removed, not the dictionary with the rest of the values.  You 
probably want something more like:

for e in event_dicts:
del e['_sa_instance_state']
(There's not really any point popping the value if you're not going to 
do anything with it - just delete the key from the dictionary)


--
Mark.
--
https://mail.python.org/mailman/listinfo/python-list


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

2024-03-22 Thread Frank Millman via Python-list

On 2024-03-22 1:23 PM, Frank Millman via Python-list wrote:

On 2024-03-22 12:09 PM, Frank Millman via Python-list wrote:


I am no expert. However, I do have something similar in my app, and it 
works.


I do not use 'await future', I use 'asyncio.wait_for(future)'.



I tested it and it did not work.

I am not sure, but I think the problem is that you have a mixture of 
blocking and non-blocking functions.


Here is a version that works. However, it is a bit different, so I don't 
know if it fits your use case.


I have replaced the threads with background asyncio tasks.

I have replaced instances of queue.Queue with asyncio.Queue.

Frank

===

import asyncio

in_queue = asyncio.Queue()
out_queue = asyncio.Queue()

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

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

async def main():
     asyncio.create_task(worker())  # start a background task
     asyncio.create_task(finalizer())  # ditto
     future = asyncio.get_event_loop().create_future()
     await in_queue.put(future)
     print(f"main put future: {future}")
     result = await asyncio.wait_for(future, timeout=None)
     print(result)

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

     # this is the preferred way to start an asyncio app
     asyncio.run(main())




One more point.

If I change 'await asyncio.wait_for(future, timeout=None)' back to your 
original 'await future', it still works.


--
https://mail.python.org/mailman/listinfo/python-list


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

2024-03-22 Thread Frank Millman via Python-list

On 2024-03-22 12:09 PM, Frank Millman via Python-list wrote:


I am no expert. However, I do have something similar in my app, and it 
works.


I do not use 'await future', I use 'asyncio.wait_for(future)'.



I tested it and it did not work.

I am not sure, but I think the problem is that you have a mixture of 
blocking and non-blocking functions.


Here is a version that works. However, it is a bit different, so I don't 
know if it fits your use case.


I have replaced the threads with background asyncio tasks.

I have replaced instances of queue.Queue with asyncio.Queue.

Frank

===

import asyncio

in_queue = asyncio.Queue()
out_queue = asyncio.Queue()

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

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

async def main():
asyncio.create_task(worker())  # start a background task
asyncio.create_task(finalizer())  # ditto
future = asyncio.get_event_loop().create_future()
await in_queue.put(future)
print(f"main put future: {future}")
result = await asyncio.wait_for(future, timeout=None)
print(result)

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

# this is the preferred way to start an asyncio app
asyncio.run(main())


--
https://mail.python.org/mailman/listinfo/python-list


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

2024-03-22 Thread Lars Liedtke via Python-list

Sorry, must have missed that :-/


Lars Liedtke
Lead Developer

[Tel.]  +49 721 98993-
[Fax]   +49 721 98993-
[E-Mail]l...@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 
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 22.03.24 um 08:58 schrieb Chris Angelico via Python-list:

On Fri, 22 Mar 2024 at 18:35, 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.




Did you try searching their documentation?

https://flask.palletsprojects.com/en/3.0.x/async-await/

ChrisA

--
https://mail.python.org/mailman/listinfo/python-list


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

2024-03-22 Thread Frank Millman via Python-list

On 2024-03-20 10:22 AM, Thomas Nyberg via Python-list wrote:


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: 
worker got future: 
worker sleeped
finalizer got future: 
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


Hi Thomas

I am no expert. However, I do have something similar in my app, and it 
works.


I do not use 'await future', I use 'asyncio.wait_for(future)'.

HTH

Frank Millman


--
https://mail.python.org/mailman/listinfo/python-list


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

2024-03-22 Thread Thomas Nyberg via Python-list

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: 
worker got future: 
worker sleeped
finalizer got future: 
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]    l...@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 
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: 
worker got future: 
worker sleeped
finalizer got future: 
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.



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

2024-03-22 Thread Chris Angelico via Python-list
On Fri, 22 Mar 2024 at 18:35, 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.
>

Did you try searching their documentation?

https://flask.palletsprojects.com/en/3.0.x/async-await/

ChrisA
-- 
https://mail.python.org/mailman/listinfo/python-list


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

2024-03-22 Thread Lars Liedtke via Python-list

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]l...@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 
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: 
worker got future: 
worker sleeped
finalizer got future: 
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
--
https://mail.python.org/mailman/listinfo/python-list