Reputation: 8631
I have a class Sensor
which has one numeric value num
. It has an async
method update
, which updates the num
every second in an infinite loop.
I want to initiate the class and call the method update
, keep it running and return the control to the main program to access the value of the num
after some time. I am using asyncio
but do not know how to invoke the method such that the concurrent running of the loop and variable access is feasible.
Code:
import asyncio
import time
class Sensor:
def __init__(self, start=0):
self.num = start
async def update(self):
print(f"Starting Updates{self.num}")
while True:
self.num += 1
print(self.num)
await asyncio.sleep(1)
if __name__ == "__main__":
print("Main")
sensor = Sensor()
# asyncio.run(sensor.update())
# asyncio.ensure_future(sensor.update())
future = asyncio.run_coroutine_threadsafe(sensor.update(), asyncio.new_event_loop())
print("We are back")
print(f"current value: {sensor.num}")
time.sleep(4)
print(f"current value: {sensor.num}")
This gives me output of 0
before and after waiting for 4 seconds, which means the update
method is not running behind. run()
does not return the control at all.
Which method should I call to invoke the infinite loop in the background?
Upvotes: 0
Views: 1583
Reputation: 84
According to documents for running tasks concurrently, you should use gather
. For example, your code will be something like this:
import asyncio
import time
class Sensor:
def __init__(self, start=0):
self.num = start
async def update(self):
print(f"Starting Updates{self.num}")
while True:
self.num += 1
print(self.num)
await asyncio.sleep(1)
async def print_value(sensor):
print("We are back")
print(f"current value: {sensor.num}")
await asyncio.sleep(4)
print(f"current value: {sensor.num}")
async def main():
print("Main")
sensor = Sensor()
await asyncio.gather(sensor.update(), print_value(sensor))
if __name__ == "__main__":
asyncio.run(main())
Upvotes: 0
Reputation: 155056
To use asyncio.run_coroutine_threadsafe
, you need to actually run the event loop, in a separate thread. For example:
sensor = Sensor()
loop = asyncio.new_event_loop()
threading.Thread(target=loop.run_forever).start()
future = asyncio.run_coroutine_threadsafe(sensor.update(), loop)
...
loop.call_soon_threadsafe(loop.stop)
Upvotes: 2