I'm trying to update the sliders in interactive.py from GANSpace with messages from python-osc.
Ideally the on_draw function should run after receiving a series of OSC messages.
But I'm having trouble with implementing it, because the serve.forever() function is blocking and i can't figure out how to implement the async version.
When i do like this:
def set_slider_osc(addr, args):
print("[{0}] ~ {1}".format(args, addr))
#print(re.split('/',addr)[2])
if "/0" in addr:
ui_state.sliders[0].set(args)
if "/1" in addr:
ui_state.sliders[1].set(args)
async def loop():
while not pending_close:
root.update()
app.update()
on_draw()
reposition_toolbar()
await asyncio.sleep(0)
async def init_main():
setup_model()
setup_ui()
resample_latent()
pending_close = False
dispatcher = dispatcher.Dispatcher()
dispatcher.map("/Chroma/*", set_slider_osc)
server = AsyncIOOSCUDPServer(("127.0.0.1", 8000), dispatcher, asyncio.get_event_loop())
transport, protocol = await server.create_serve_endpoint() # Create datagram endpoint and start serving
await loop() # Enter main loop of program
transport.close() # Clean up serve endpoint
root.destroy()
#
if __name__=='__main__':
await init_main()
I get the error that i try to run 'await' outside a function and another way i tried it seemed like there already was a main loop running and therefore couldn't run a new..
I know it's allot to aks people to install GANSpace, but hope someone may shine some light on how one could do this.
await cannot be used outside of a function defined with async def. You are trying to use it outside a function. The fix is to run init_main in an event loop.
import asyncio
asyncio.run(init_main())
Related
I have two bots, one is using pydle for IRC, like:
async def start_ircbot ():
try:
client = MyOwnBot(NICK,
realname=REALNAME,
sasl_username=SASL_USERNAME,
sasl_password=SASL_PASSWORD,
sasl_identity=SASL_IDENTITY,)
loop = asyncio.get_event_loop()
asyncio.ensure_future(client.connect(HOST, PORT, tls=True, tls_verify=False), loop=loop)
loop.run_forever()
loop.close()
except Exception as e:
print (e)
and another is using telethon for Telegram:
#client.on(events.NewMessage)
async def my_event_handler(event):
...
async def start_client ():
print ("Telegram monitor started...")
await client.start()
await client.run_until_disconnected()
Both of them work without problem separately.
Now, I want to integrate both of them, I tried to launch both of them in my main function like this,
import Notifier
...
async def main():
await asyncio.gather (Notifier.start_client (), start_ircbot ())
asyncio.run(main())
It starts without issue but my_event_handler seems never to get new messages. If I swap the order of functions:
await asyncio.gather (start_ircbot (), Notifier.start_client ())
The script will be stuck at launching, I suspect it has to be something within events loops and tried some different methods but without luck, could anyone shed light on this for me?
Newer Python versions are removing the loop parameter from most methods, so you should try to avoid using it. As long as you don't use asyncio.run (which creates a new loop) or you don't create a new loop yourself, both libraries should be using the default loop from the main thread (I can't speak for pydle, but Telethon does this).
As long as the asyncio event loop is running, Telethon should have no trouble receiving updates. You can use client.loop to make sure it's using the same loop:
tlclient = TelegramClient(...)
irclient = MyOwnBot(...)
#tlclient.on(events.NewMessage)
async def my_event_handler(event):
...
async def main():
await tlclient.start()
await irclient.connect(HOST, PORT, tls=True, tls_verify=False), loop=tlclient.tlclient)
await tlclient.run_until_disconnected() # similar to loop.run_forever() but stops when the client disconnects
client.loop.run_until_complete(main())
I'm new to websockets and asyncio and I'm trying to get a simple example working. I would like to create a server that accepts connections from multiple clients and concurrently runs a loop that sends a message to every connection once a second. I'm also trying to use asyncio.run() which I believe is preferred to the get_event_loop() code on which many examples are based.
Here's my code so far:
import asyncio
import websockets
USERS = set()
async def register(websocket, path):
USERS.add(websocket)
await websocket.send("Successfully registered")
async def count():
count = 0
while True:
print(f"Iteration: {count}")
if USERS:
for user in USERS:
await user.send("Sending message back to client")
await asyncio.sleep(1)
count +=1
async def serve():
server = await websockets.serve(register, 'localhost', 8765)
await server.wait_closed()
print("Server closed")
async def main():
await asyncio.gather(count(), serve())
asyncio.run(main())
When I run this the count coroutine works until I make a connection from a client. At this point the connection is successfully registered but when I try to send a message back to the client in count() I get an error because the connection is already closed. How should I change my code to stop this from happening?
How should I change my code to stop this from happening?
The problem might be that your handler, the register coroutine, is returning immediately, which prompts websockets to close the connection. Try to change it like this:
async def register(websocket, path):
USERS.add(websocket)
await websocket.send("Successfully registered")
await asyncio.Event().wait()
If that helps, you can put the event in USERS along with websocket, so that you have a way to terminate the connection to the client when you want to.
I have a large python app (now converted to python3) where the main code ran in an infinite loop.
while (True):
#Do loads of stuff, connect to rs485 devices, obtain their status etc.
I'm wanting to use websockets with this app. I've now converted it so the structure is:
def mainPoll():
#Do loads of stuff (omitted for brevity)
while (True):
mainPoll()
The websockets sample code ( from HERE) I have as a starting point is:
import asyncio
import datetime
import random
import websockets
async def time(websocket, path):
while True:
now = datetime.datetime.utcnow().isoformat() + "Z"
await websocket.send(now)
await asyncio.sleep(random.random() * 3)
start_server = websockets.serve(time, "127.0.0.1", 5678)
asyncio.get_event_loop().run_until_complete(start_server)
asyncio.get_event_loop().run_forever()
EDIT I've been trying to combine the two. Mycode below will run mainPoll() asynchronously once using create_task. Is there a better way to keep running it that calling create_task again at the end of mainPoll?
async def mainPoll():
#do loads of stuff (omitted for brevity)
#then create another task to run myself again?!?!?!
#IS THIS NEXT LINE THE BEST WAY?
asyncio.get_event_loop().create_task(mainPoll())
#end of mainPoll
async def xtime(websocket, path):
while True:
now = str(time.time())
await websocket.send(now)
await asyncio.sleep(random.random() * 3)
start_server = websockets.serve(xtime, "0.0.0.0", 5678)
asyncio.get_event_loop().run_until_complete(start_server)
poll=asyncio.get_event_loop().create_task(mainPoll())
asyncio.get_event_loop().run_forever()
I'd really appreciate some pointers here as the websockets code doesn't seem to match any of the asyncio examples I can find. Many thanks.
mainPoll needs to be an async function. There is no need to re-create the task as shown in the question - it is fine for it to contain a while True loop, as long as something is awaited inside the loop. If you need blocking APIs there, use run_in_executor to await them without disturbing websockets.
I've been stuck on this for a while, hopefully someone can shed some light!
I want to set up a websocket connection between JavaScript in a browser, and a Python function (currently using the websockets module).
The Python function should always listen() for messages send by the browser
Occasionally I want to send messages to the browser from an external script or function, for example by calling a function speak()
Here is my code currently:
listen
async def listen(self, websocket, path):
while True:
need_update = await websocket.recv()
print(f'< {need_update}')
start_server = websockets.serve(listen(), 'localhost', 8765)
asyncio.get_event_loop().run_until_complete(start_server)
asyncio.get_event_loop().run_forever()
speak
async def speak(data):
async with websockets.connect('ws://localhost:8765') as websocket:
await websocket.send(data)
print(f'> {data}')
asyncio.get_event_loop().run_until_complete(speak(input("? ")))
With this method, the speak function will only send messages to the Python listen function, the JavaScript code receives nothing.
Conversely, I can start both functions together with asyncio.gather(...) but then I can't call speak from an external function.
Really not sure how to get around this.
I never managed to work this out, but switching to the socket.io library solves the problem I was having.
I am using the Sanic as the server and try to handle multiple request concurrently.
I have used the await for the encode function(I use for loop to simulate do something) but when I try the time curl http://0.0.0.0:8000/ in two separate consoles, it doesn't run concurrently.
I have searched google but only find event_loop but it is to schedule registered conroutines.
How do I await the for loop so the requests won't be blocked?
Thank you.
from sanic import Sanic
from sanic import response
from signal import signal, SIGINT
import asyncio
import uvloop
app = Sanic(__name__)
#app.route("/")
async def test(request):
# await asyncio.sleep(5)
await encode()
return response.json({"answer": "42"})
async def encode():
print('encode')
for i in range(0, 300000000):
pass
asyncio.set_event_loop(uvloop.new_event_loop())
server = app.create_server(host="0.0.0.0", port=8000)
loop = asyncio.get_event_loop()
task = asyncio.ensure_future(server)
signal(SIGINT, lambda s, f: loop.stop())
try:
loop.run_forever()
except:
loop.stop()
Running for i in range() is blocking. If you change that to put your await asyncio.sleep(5) into the encode method, you will see that it operates as expected.
#app.route("/")
async def test(request):
await encode()
return response.json({"answer": "42"})
async def encode():
print('encode')
await asyncio.sleep(5)
When you call await encode() and encode is a blocking method, then it still is going to block because you are not "awaiting" anything else. Your thread is still locked up.
You could also add another worker:
app.create_server(worker=2)
Try looking through this answer
Since the async handler is actually running in an eventloop, it is running asynchronously as callback rather than concurrently.
loop.run_forever() would call loop._run_once over and over again to run all the registered event, each await would stop the coroutine and yield control back to the eventloop and eventloop arrange to run the next event.
So basically if you don't want blocking in a long running for-loop, you need to manually hand over the control back to the eventloop inside the for-loop, see the issue about relinquishing control:
async def encode():
print('encode')
for i in range(0, 300000000):
await asyncio.sleep(0)
Here is a quote from Guido:
asyncio.sleep(0) means just that -- let any other tasks run and then
come back here.