"실행 후 잊어 버리기"python async / await
때때로 발생해야하는 중요하지 않은 비동기 작업이 있지만 완료 될 때까지 기다리고 싶지 않습니다. Tornado의 코 루틴 구현에서는 단순히 yield
키워드 를 생략하여 비동기 함수를 "실행하고 잊을"수 있습니다 .
나는 파이썬 3.5에서 발표 된 새로운 async
/ await
구문으로 "실행하고 잊어 버리는"방법을 알아 내려고 노력해 왔습니다 . 예 : 단순화 된 코드 스 니펫 :
async def async_foo():
print("Do some stuff asynchronously here...")
def bar():
async_foo() # fire and forget "async_foo()"
bar()
하지만 bar()
실행되지 않고 대신 런타임 경고가 표시됩니다.
RuntimeWarning: coroutine 'async_foo' was never awaited
async_foo() # fire and forget "async_foo()"
업데이트 :
교체 asyncio.ensure_future
로 asyncio.create_task
파이썬> = 3.7 그것은 최신의, 더 좋은 방법을 사용하고있는 모든 곳에서 경우 산란 작업에 .
asyncio.Task를 "실행하고 잊어 버리기"
파이썬 문서에 따르면 "백그라운드에서"실행asyncio.Task
하기 위해 코 루틴을 시작할 수 있습니다 . asyncio.ensure_future
함수에 의해 생성 된 작업 은 실행을 차단하지 않습니다 (따라서 함수가 즉시 반환됩니다!). 이것은 귀하가 요청한대로 "실행하고 잊어 버리는"방법처럼 보입니다.
import asyncio
async def async_foo():
print("async_foo started")
await asyncio.sleep(1)
print("async_foo done")
async def main():
asyncio.ensure_future(async_foo()) # fire and forget async_foo()
# btw, you can also create tasks inside non-async funcs
print('Do some actions 1')
await asyncio.sleep(1)
print('Do some actions 2')
await asyncio.sleep(1)
print('Do some actions 3')
if __name__ == '__main__':
loop = asyncio.get_event_loop()
loop.run_until_complete(main())
산출:
Do some actions 1
async_foo started
Do some actions 2
async_foo done
Do some actions 3
이벤트 루프가 완료된 후 작업이 실행되면 어떻게됩니까?
asyncio는 이벤트 루프가 완료되는 순간 작업이 완료 될 것으로 예상합니다. 따라서 다음으로 변경할 경우 main()
:
async def main():
asyncio.ensure_future(async_foo()) # fire and forget
print('Do some actions 1')
await asyncio.sleep(0.1)
print('Do some actions 2')
프로그램이 완료된 후 다음 경고가 표시됩니다.
Task was destroyed but it is pending!
task: <Task pending coro=<async_foo() running at [...]
이벤트 루프가 완료된 후 모든 보류중인 작업 을 기다릴 수있는 것을 방지하려면 :
async def main():
asyncio.ensure_future(async_foo()) # fire and forget
print('Do some actions 1')
await asyncio.sleep(0.1)
print('Do some actions 2')
if __name__ == '__main__':
loop = asyncio.get_event_loop()
loop.run_until_complete(main())
# Let's also finish all running tasks:
pending = asyncio.Task.all_tasks()
loop.run_until_complete(asyncio.gather(*pending))
작업을 기다리는 대신 종료
Sometimes you don't want to await tasks to be done (for example, some tasks may be created to run forever). In that case, you can just cancel() them instead of awaiting them:
import asyncio
from contextlib import suppress
async def echo_forever():
while True:
print("echo")
await asyncio.sleep(1)
async def main():
asyncio.ensure_future(echo_forever()) # fire and forget
print('Do some actions 1')
await asyncio.sleep(1)
print('Do some actions 2')
await asyncio.sleep(1)
print('Do some actions 3')
if __name__ == '__main__':
loop = asyncio.get_event_loop()
loop.run_until_complete(main())
# Let's also cancel all running tasks:
pending = asyncio.Task.all_tasks()
for task in pending:
task.cancel()
# Now we should await task to execute it's cancellation.
# Cancelled task raises asyncio.CancelledError that we can suppress:
with suppress(asyncio.CancelledError):
loop.run_until_complete(task)
Output:
Do some actions 1
echo
Do some actions 2
echo
Do some actions 3
echo
This is not entirely asynchronous execution, but maybe run_in_executor() is suitable for you.
def fire_and_forget(task, *args, **kwargs):
loop = asyncio.get_event_loop()
if callable(task):
return loop.run_in_executor(None, task, *args, **kwargs)
else:
raise TypeError('Task must be a callable')
def foo():
#asynchronous stuff here
fire_and_forget(foo)
Thank you Sergey for the succint answer. Here is the decorated version of the same.
import asyncio
import time
def fire_and_forget(f):
def wrapped(*args, **kwargs):
return asyncio.get_event_loop().run_in_executor(None, f, *args, *kwargs)
return wrapped
@fire_and_forget
def foo():
time.sleep(1)
print("foo() completed")
print("Hello")
foo()
print("I didn't wait for foo()")
Produces
>>> Hello
>>> foo() started
>>> I didn't wait for foo()
>>> foo() completed
참고URL : https://stackoverflow.com/questions/37278647/fire-and-forget-python-async-await
'IT박스' 카테고리의 다른 글
단위 테스트가 메서드가 sys.exit ()를 호출한다고 주장 할 수 있습니까? (0) | 2020.09.25 |
---|---|
JSF의 국제화, 언제 메시지 번들과 리소스 번들을 사용합니까? (0) | 2020.09.25 |
react-router에서 쿼리 매개 변수를 프로그래밍 방식으로 어떻게 업데이트합니까? (0) | 2020.09.25 |
Windows에서 특정 파일이 열려 있는지 어떻게 확인할 수 있습니까? (0) | 2020.09.25 |
초보 개발자를위한 Django vs web2py (0) | 2020.09.25 |