#python #.net #asynchronous #python-asyncio #python.net
#python #.net #асинхронный #python-asyncio #python.net
Вопрос:
Я использую стороннюю программу.Библиотека Net в Python 3.6 через Python для .Net, который использует обработчики событий для предоставления асинхронных данных моему приложению, аналогично приведенному ниже игрушечному примеру:
import clr
from System import Timers
def tock(__, args):
print(args.SignalTime)
timer = Timers.Timer()
timer.Interval = 1000
timer.Elapsed = tock
timer.Enabled = True
while True:
pass
Я хотел бы передать эти данные в асинхронный генератор, что-то вроде:
import clr
from System import Timers
async def tock(__, args):
yield args.SignalTime
async def main():
result = await tock
print(result)
timer = Timers.Timer()
timer.Interval = 1000
timer.Elapsed = tock
timer.Enabled = True
while true:
result = await timer
print result
Очевидно, что простое включение asyc
и yield
в функцию обработчика событий и await
включение таймера этого не сделают, но есть ли простой способ добиться этого?
Ответ №1:
Поскольку «асинхронные» данные поступают из другого потока, вам понадобится мост между asyncio и потоком, который вызывает tock
. На стороне asyncio вам нужно будет реализовать асинхронный генератор и выполнить итерацию по нему с помощью async for
цикла. Например (непроверенный):
import clr, asyncio
from System import Timers
def adapt_sync_to_async():
# Adapt a series of sync callback invocations to an async
# iterator. Returns an async iterator and a feed callback
# such that the async iterator will produce a new item
# whenever the feed callback is fed one.
loop = asyncio.get_event_loop()
queue = asyncio.Queue()
def feed(item):
loop.call_soon_threadsafe(queue.put_nowait, item)
async def drain():
while True:
yield await queue.get()
return drain, feed
tock, feed_tock = adapt_sync_to_async()
async def main():
async for result in tock():
print(result)
timer = Timers.Timer()
timer.Interval = 1000
timer.Elapsed = lambda _, args: feed_tock(args.SignalTime)
timer.Enabled = True
asyncio.get_event_loop().run_until_complete(main())
Комментарии:
1. Спасибо, это решение работает (после добавления
import asyncio
, которое я забыл изначально)