Python 3.5에서 코루틴과 미래/작업의 차이점은 무엇입니까?
더미 함수가 있다고 가정합니다.
async def foo(arg):
result = await some_remote_call(arg)
return result.upper()
다음의 차이점은 무엇입니까?
import asyncio
coros = []
for i in range(5):
coros.append(foo(i))
loop = asyncio.get_event_loop()
loop.run_until_complete(asyncio.wait(coros))
그리고:
import asyncio
futures = []
for i in range(5):
futures.append(asyncio.ensure_future(foo(i)))
loop = asyncio.get_event_loop()
loop.run_until_complete(asyncio.wait(futures))
참고: 예제는 결과를 반환하지만, 이것은 질문의 초점이 아닙니다.반환 가치가 중요한 경우 사용gather()
에 wait()
.
수익률과 상관없이, 저는 명확한 정보를 찾고 있습니다.ensure_future()
.wait(coros)
그리고.wait(futures)
둘 다 코루틴을 운영하기 때문에, 코루틴은 언제 그리고 왜 포장되어야 합니까.ensure_future
?
3의 Python 3.5를 하여 많은 방법입니까?async
?
추가 크레딧을 위해서, 제가 전화를 일괄 처리하고 싶으면 어떻게 합니까?예를 들어, 전화를 해야 합니다.some_remote_call(...)
1000번이지만 1000번의 동시 연결로 웹 서버/데이터베이스/등을 크래시하고 싶지 않습니다.은 스레드나 할 수 , 스드또는프풀실수있사, 위있까습니방이법한만지이를로 할 수 있는 이 있습니까?asyncio
?
2020년 업데이트(파이썬 3.7+):이 스니펫을 사용하지 마십시오.대신 다음을 사용합니다.
import asyncio
async def do_something_async():
tasks = []
for i in range(5):
tasks.append(asyncio.create_task(foo(i)))
await asyncio.gather(*tasks)
def do_something():
asyncio.run(do_something_async)
또한 비동기식에 대한 강력한 타사 대안인 Trio를 사용하는 것도 고려해 보십시오.
코루틴은 값을 산출하고 외부로부터 값을 수용할 수 있는 생성기 함수입니다.코루틴을 사용하면 함수 실행을 일시 중지하고 나중에 다시 시작할 수 있습니다.네트워크 작업의 경우 응답을 기다리는 동안 함수 실행을 일시 중지하는 것이 좋습니다.다른 기능을 실행하는 데 시간을 사용할 수 있습니다.
는 미는마치와 .Promise
Javascript 입니다.그것은 미래에 구체화될 가치의 자리 표시자와 같습니다.위에서 언급한 경우, 네트워크 I/O에서 대기하는 동안 함수는 컨테이너를 제공할 수 있습니다. 즉, 작업이 완료되면 컨테이너에 값을 채울 것이라는 약속입니다.우리는 미래의 물체를 붙잡고 그것이 실현되면, 우리는 실제 결과를 얻기 위해 그것에 대한 방법을 호출할 수 있습니다.
직접 답변:필요없습니다ensure_future
결과가 필요 없는 경우.결과가 필요하거나 발생한 예외를 검색하는 경우 유용합니다.
추가 학점:나는 선택하고 통과할 것입니다.Executor
최대 작업자 수를 제어하는 인스턴스입니다.
설명 및 샘플 코드
첫 번째 예제에서는 코루틴을 사용하고 있습니다. 그wait
함수는 코루틴의 다발을 가지고 그것들을 함께 결합합니다.그렇게wait()
모든 코루틴이 소진되면 종료됩니다(모든 값을 반환함/반환함).
loop = get_event_loop() #
loop.run_until_complete(wait(coros))
그run_until_complete
메소드는 실행이 완료될 때까지 루프가 활성 상태인지 확인합니다.이 경우 비동기 실행 결과를 얻을 수 없습니다.
에서는 두번예는다사있습고니다용하음을에서째▁the있을 사용하고 있습니다.ensure_future
하는 Task
Future
코루틴은 당신이 호출할 때 메인 이벤트 루프에서 실행되도록 예약되어 있습니다.ensure_future
반환된 미래/작업 개체에는 아직 값이 없지만 시간이 지남에 따라 네트워크 작업이 완료되면 미래 개체에 작업 결과가 저장됩니다.
from asyncio import ensure_future
futures = []
for i in range(5):
futures.append(ensure_future(foo(i)))
loop = get_event_loop()
loop.run_until_complete(wait(futures))
그래서 이 예에서 우리는 코루틴을 사용하는 대신 미래를 사용하는 것을 제외하고는 같은 일을 하고 있습니다.
비동기/코루틴/미래를 사용하는 방법의 예를 살펴보겠습니다.
import asyncio
async def slow_operation():
await asyncio.sleep(1)
return 'Future is done!'
def got_result(future):
print(future.result())
# We have result, so let's stop
loop.stop()
loop = asyncio.get_event_loop()
task = loop.create_task(slow_operation())
task.add_done_callback(got_result)
# We run forever
loop.run_forever()
여기서는 다음을 사용했습니다.create_task
에 있는 loop
물건. ensure_future
주 이벤트 루프에서 작업을 예약합니다.이 방법을 사용하면 선택한 루프에서 코루틴을 예약할 수 있습니다.
또한 다음을 사용하여 콜백을 추가하는 개념도 볼 수 있습니다.add_done_callback
메서드가 작업 개체에 있습니다.
A Task
이라done
코루틴이 값을 반환하거나, 예외를 제기하거나, 취소되는 경우.이러한 인시던트를 확인하는 방법이 있습니다.
다음과 같은 주제에 대한 블로그 게시물을 작성했습니다.
- http://masnun.com/2015/11/13/python-generators-coroutines-native-coroutines-and-async-await.html
- http://masnun.com/2015/11/20/python-asyncio-future-task-and-the-event-loop.html
- http://masnun.com/2015/12/07/python-3-using-blocking-functions-or-codes-with-asyncio.html
물론 자세한 내용은 공식 매뉴얼 https://docs.python.org/3/library/asyncio.html 에서 확인하실 수 있습니다.
TL;DR
- 함수 (코루틴함호출수((()
async def
실행하지 않습니다.생성기 함수가 생성기 개체를 반환하는 것과 같은 코루틴 개체를 반환합니다. await
코루틴에서 값을 검색합니다. 즉, 코루틴을 "검색"합니다.eusure_future/create_task
코루틴을 래핑하고 다음 반복 시 이벤트 루프에서 실행되도록 예약하지만 종료될 때까지 기다리지 않습니다. 데몬 스레드와 같습니다.- 코루틴 또는 코루틴을 포장하는 작업을 대기하면 항상 코루틴에서 반환된 결과를 검색할 수 있습니다. 차이점은 실행 순서입니다.
몇 가지 코드 예제
먼저 몇 가지 조건을 삭제합니다.
- 함수,즉 당신이 루틴함수하, 는이것신당코 하는 .
async def
s; - 코루틴 객체, 코루틴 함수를 "호출"했을 때 얻을 수 있는 것;
- 작업, 이벤트 루프에서 실행할 코루틴 개체를 감싸는 개체입니다.
- 수 있는,이 할 수 있는 것, 기다릴 수 있는 것.
await
예를 들어 작업, 미래 또는 일반 코루틴 객체.
어용coroutine
상황에 따라 코루틴 함수와 코루틴 객체가 모두 될 수 있지만 차이를 구분하기에 충분히 쉬울 것입니다.
1, 제1조await
에.
는 두 개의. 두 개 의 코 루 만 들 을 고 틴 만 들 고 , ▁we두 ▁two 을await
하나, 그리고 용도create_task
다른 하나를 실행합니다.
import asyncio
import time
# coroutine function
async def log_time(word):
print(f'{time.time()} - {word}')
async def main():
coro = log_time('plain await')
task = asyncio.create_task(log_time('create_task')) # <- runs in next iteration
await coro # <-- run directly
await task
if __name__ == "__main__":
asyncio.run(main())
다음과 같은 결과를 얻을 수 있습니다. 예상대로 플레인 코루틴이 먼저 실행되었습니다.
1539486251.7055213 - plain await
1539486251.7055705 - create_task
ㅠㅠcoro
되었고, 실었며으되행직접,며으▁was▁directly▁executed,task
다음 반복에서 실행되었습니다.
사례 2, 이벤트 루프에 대한 제어 권한 부여
전로화에 으로써.asyncio.sleep(1)
컨트롤이 루프로 반환되면 다른 결과가 표시됩니다.
async def main():
coro = log_time('plain await')
task = asyncio.create_task(log_time('create_task')) # <- runs in next iteration
await asyncio.sleep(1) # <- loop got control, and runs task
await coro # <-- run directly
await task
다음과 같은 결과가 표시됩니다. 실행 순서가 반대로 적용됩니다.
1539486378.5244057 - create_task
1539486379.5252144 - plain await
를 부를 때asyncio.sleep(1)
은 이벤트 루프로 "" "" " " " " " " " 를 합니다.task
에해의창에 의해 되었습니다.create_task
했지만, 비록우코기루먼능을호저, .await
방금 코루틴을 만들었습니다. 자동으로 시작되지 않습니다.그리고 나서, 우리는 새로운 코루틴을 만들고 그것을 포장합니다.create_task
러불,creat_task
에서는 코루틴을 래핑할 뿐만 아니라 다음 반복 시 실행할 작업을 예약합니다. 결과, 결적으로과,create_task
앞에 됩니다.plain await
.
여기서 마법은 루프에 제어권을 다시 주는 것입니다. 사용할 수 있습니다.asyncio.sleep(0)
동일한 결과를 얻기 위해.
모든 차이가 있은 후에도 같은 것이 있습니다. 코루틴이나 코루틴을 포장하는 작업, 즉 대기 중인 작업을 기다리면 언제든지 결과를 검색할 수 있습니다.
후드 아래
asyncio.create_task
출들asyncio.tasks.Task()
전화가 올 것입니다.loop.call_soon
.그리고.loop.call_soon
을 작을수니다합에 넣습니다.loop._ready
루프가 반복될 때마다 모든 콜백을 확인합니다.loop._ready
그리고 그것을 운영합니다.
asyncio.wait
,asyncio.ensure_future
그리고.asyncio.gather
실제로 전화를 걸었습니다loop.create_task
직간접적으로
문서에도 참고:
콜백은 등록된 순서대로 호출됩니다.각 콜백은 정확히 한 번 호출됩니다.
https://github.com/python/asyncio/blob/master/asyncio/tasks.py#L346, 에 연결된 빈센트의 논평은 다음을 보여줍니다.wait()
을 코틴을감다싼으로 .ensure_future()
당신을 위해!
다시 말해서, 우리는 미래가 필요하고, 코루틴은 조용히 그것들로 바뀔 것입니다.
코루틴/미래 배치 방법에 대한 확실한 설명이 나오면 이 답변을 업데이트하겠습니다.
임무들
- 미래에 포장된 코루틴입니다.
- 클래스 작업은 클래스 미래의 하위 클래스입니다.
- 그래서 wait에서도 작동합니다!
- 맨 코루틴과 어떻게 다릅니까?
- 기다리지 않고 진행할 수 있습니다.
- 당신이 다른 것을 기다리는 한, 즉.
- 기다리다[기다리다]
- 당신이 다른 것을 기다리는 한, 즉.
에 두고, 이을염두두고에것,고,ensure_future
사용자가 작업을 기다리는지 여부에 관계없이 미래의 결과가 계산되므로 작업을 생성하기 위한 이름으로 사용할 수 있습니다.이렇게 하면 다른 작업을 기다리는 동안 이벤트 루프가 작업을 완료할 수 있습니다.Python 3.7에서는create_task
미래를 보장하는 것이 선호되는 방법입니다.
참고: Guido의 슬라이드에서 "수익률"을 현대성을 위해 "기다림"으로 변경했습니다.
이미 매우 유용한 답변이 몇 개 있지만 모든 뉘앙스를 다루지는 않습니다.특히, 받아들여진 대답은 더 이상 정확하지 않습니다.
사용하면 안 됩니다.wait
코루틴 포함 - 새 버전의 라이브러리와 호환됩니다.
버전 3.8 이후에는 사용되지 않습니다. 버전 3.11에서는 제거될 예정입니다. 코루틴 개체를 대기()에 직접 전달하는 것은 더 이상 사용되지 않습니다.
그리고 설명서의 또 다른 설명은 깊은 이해에 유용할 수 있습니다.『 』의 결과wait
의 먼저 코루틴을 미래로 포장해야 .create_task
이 (에)ensure_future
).
wait()는 자동으로 작업으로 코루틴을 예약하고 나중에 암묵적으로 생성된 작업 개체를 (완료, 보류 중) 세트로 반환합니다.따라서 다음 코드가 예상대로 작동하지 않습니다.
async def foo(): return 42 coro = foo() done, pending = await asyncio.wait({coro}) if coro in done: # This branch will never be run!
위의 스니펫을 수정하는 방법은 다음과 같습니다.
return 42 task = asyncio.create_task(foo()) done, pending = await asyncio.wait({task}) if task in done: # Everything will work as expected now.
언급URL : https://stackoverflow.com/questions/34753401/difference-between-coroutine-and-future-task-in-python-3-5
'programing' 카테고리의 다른 글
이름이 올바른 식별자가 아니기 때문에 exec이 실패했습니까? (0) | 2023.05.06 |
---|---|
Azure App 서비스 메모리 사용량입니다.어디에서 전체 고장을 확인할 수 있습니까? (0) | 2023.05.06 |
git diff 도구, 직렬이 아닌 모든 diff 파일을 즉시 엽니다. (0) | 2023.05.06 |
어떻게 만들까요?시스템 트레이에서만 실행되는 NET Windows Forms 응용 프로그램? (0) | 2023.05.06 |
mongoose를 사용하여 mongodb에서 컬렉션의 만료 시간 설정 (0) | 2023.05.06 |