itsource

런타임 오류:이 이벤트 루프가 python에서 이미 실행되고 있습니다.

mycopycode 2023. 9. 4. 19:47
반응형

런타임 오류:이 이벤트 루프가 python에서 이미 실행되고 있습니다.

코드가 호출되기 때문에 이 오류가 발생하는 것 같습니다.asyncio.get_event_loop().run_until_complete(foo()) 번.한은 두번. 한번.foo() 두 입니다.foo()그렇다면 제 질문은: 왜 이것이 문제가 되어야 하는가 하는 것입니다.내가 왜 이 루프가 작동하는 것에 신경을 써야 합니까?


제 생각에 이 질문에 대한 편집이 이루어졌고, 제 생각에 그것을 모호하게 했습니다(어떤 사람들은 규칙을 이해하지 않고 따르는 것을 선호하기 때문에 "불법적인" 단어가 제목에서 제거되었습니다).불행하게도, 이것은 혼란을 야기합니다.

저는 오류가 제기되었다는 사실에 놀라지 않습니다.저는 그것을 추적할 수 있습니다.asyncio출처와 이 도서관의 저자들이 이런 식으로 하기를 원했다는 것을 보세요, 거기에는 신비가 없습니다.도서관의 저자들이 이벤트 루프에서 루프가 이미 실행되고 있을 때 어떤 기능을 실행하기 위해 완료까지 요청하는 것은 불법이라고 결정한 이유에서 곤혹스러운 부분이 있습니다.

문제를 단 두 번의 통화로 줄일 수 있으며 사례 분석을 통해 다음 세 가지 가능성이 있음을 확인할 수 있습니다.

  1. 두 기능 모두 종료되지 않습니다.
  2. 기능 중 하나가 결국 종료됩니다.
  3. 두 기능 모두 결국 종료됩니다.

자, 이 세 가지 경우를 모두 해결할 수 있는 분별 있는 행동이 있을까요?제가 보기에, 여기에 여러 가지 제정신적인 행동이 있을 수도 있고, 아마도 있을 수도 있습니다.예:

  1. 특별한 것은 없습니다. 두 기능의 실행은 인터리브되며 예상대로 계속 실행됩니다.
  2. 루가첫번인스스다턴음코않반제다의 첫 번째 .run_until_complete() 완료될 까지 ("" 뒤에 를 표시하지 않음)run_until_complete()실행됩니다.
  3. 된 후 는 첫 객체에 을 반환합니다. 이 코드 는 " 막 함 종 호 첫 개 코 제 반 합 니 환 다 를 어 로 체 마 드 지 번 째 된 출 수 가 루 는 프 료 후 된 ▁which ▁object ▁to ▁after ▁control ▁returns 다 니 ▁term ▁code ▁invoked ▁the ▁the 마 ▁loop ▁firstrun_until_complete다른 모든 호출 사이트를 무시합니다.

이제, 저는 이 행동이 모든 사람들이 원하는 것이 아닐 수도 있다는 것을 이해할 수 있습니다.그러나 이 라이브러리는 프로그래머에게 이벤트 루프의 시작/정지를 제어하기로 결정했으므로 이러한 결정의 결과도 충족해야 합니다.한 루프를 번 코드가 이러한 작업을할 수 되어 코드가 사용하는 됩니다.asyncio(예를 들어, 실제로는 그렇습니다.)aiohttp).

nest_async를 사용하여 문제를 해결했습니다.

pip install nest-asyncio

파일에 아래 줄을 추가합니다.

import nest_asyncio
nest_asyncio.apply()
# EDIT: the __import__ line is not needed, leaving it just 
# so that the comments make sense
# __import__('IPython').embed() 

이벤트 루프 실행 중 - 비동기 프로그램의 진입점입니다.모든 코루틴, 태스크, 콜백의 실행을 관리합니다.실행 중에 루프를 실행하는 것은 의미가 없습니다. 이미 실행 중인 동일한 작업 실행자에서 작업 실행자를 실행하려고 하는 것과 같습니다.

당신은 이런 질문을 가지고 있기 때문에 비동기식이 어떻게 작동하는지 오해할 수도 있다고 생각합니다.기사를 읽어주세요 - 크지 않고 좋은 소개를 해줍니다.

업데이트:

이 루프가 이미 실행 중인 동안 이벤트 루프에서 실행할 여러 가지를 추가하는 데는 전혀 문제가 없습니다.기다리는 것만으로도 가능합니다.

await coro()  # add coro() to be run by event loop blocking flow here until coro() is finished

또는 태스크 생성:

# python 3.7+
asyncio.create_task(coro())  # add coro() to be run by event loop without blocking flow here

# This works in all Python versions but is less readable
asyncio.ensure_future(coro())

보시다시피 호출 이벤트 루프에 의해 실행되는 무언가를 만들기 위해 호출 이벤트 루프의 메서드가 필요하지 않습니다.

인 " 과이루프방법의벤트은같"run_forever또는run_until_complete일반적으로 이벤트 루프를 시작하는 방법일 뿐입니다.

run_until_complete(foo()) "": "추가"foo()합니다.foo()완료되지 않았습니다."

처음에 이 코드 묶음을 추가하면 됩니다.

!pip install nest_asyncio
import nest_asyncio
nest_asyncio.apply()

저는 이것을 후원하기 위해서가 아니라 단순히 비동기 기능을 큐잉하고 이벤트 루프가 실행되는 동안 동기화된 결과를 기다리는 것만으로는 작동하지 않는 상황을 어떻게 처리할 수 있는지 설명하기 위해 적어봅니다.

run_until_complete임의의 비동기 함수를 동기적으로 실행하기 위한 것이 아니라 전체 비동기 프로그램의 주 진입점을 실행하기 위한 것입니다.이 제약 조건은 문서에서 즉시 나타나지 않습니다.

와 같은 에 넣고 iohttp를 사용하여합니다.run_until_complete또는run_forever이벤트 루프가 이미 실행 중이므로 해당 이벤트 루프에서 독립적인 동기화 작업을 실행하고 해당 스레드 내에서 결과를 기다릴 수 없습니다.

즉, 비동기 작업을 동기 컨텍스트 내에서 실행 중인 이벤트 루프로 큐잉하여 일반 기능과 같은 결과를 얻어야 한다면 불가능할 수 있습니다.한 가지 방법은 비동기 작업이 완료되면 호출될 동기 콜백을 전달하는 것입니다.그러면 당연히 이벤트 루프 속도가 느려집니다.다른 방법은 결과를 대기열에 넣고 동기 루프에서 대기하여 이벤트 루프를 에뮬레이트하는 것입니다.

이 상황을 처리하는 또 다른 방법은 사용 중인 비동기식 http 라이브러리의 시작 및 정리 콜백 내에서 코드를 실행하는 것입니다.다음은 이 작업을 수행하는 방법의 샘플입니다.

저도 같은 문제가 있었고 nest_async 또는 asyncio를 사용하여 이 문제를 해결했습니다.

솔루션 #1

패키지를 설치하기만 하면 됩니다.

pip install nest-asyncio

그런 다음 다음 행을 추가합니다.

import nest_asyncio
nest_asyncio.apply()

솔루션 #2

nest_asyncio에서 작동하지 않는 경우 asyncio를 사용해 보십시오.

import asyncio
asyncio.set_event_loop(asyncio.new_event_loop())

사용.nest_asyncio내겐 효과가 없었어, 왜냐하면 그때aiohttp불평하기 시작했습니다.

  • RuntimeError: Timeout context manager should be used inside a task

대신에 저는 모든 전화를 교체하기로 결정했습니다.asyncio.run 이에대요함께과청한것▁▁calls▁this에 전화를 걸어 왔습니다.asyncio_run:

def asyncio_run(future, as_task=True):
    """
    A better implementation of `asyncio.run`.

    :param future: A future or task or call of an async method.
    :param as_task: Forces the future to be scheduled as task (needed for e.g. aiohttp).
    """

    try:
        loop = asyncio.get_running_loop()
    except RuntimeError:  # no event loop running:
        loop = asyncio.new_event_loop()
        return loop.run_until_complete(_to_task(future, as_task, loop))
    else:
        nest_asyncio.apply(loop)
        return asyncio.run(_to_task(future, as_task, loop))


def _to_task(future, as_task, loop):
    if not as_task or isinstance(future, Task):
        return future
    return loop.create_task(future)

두 번째 목표는 다음과 같은 것을 생각할 수 있는 것이었습니다.asyncio.run~하듯이promise.resolve월드 JS 세부터또는계로▁the▁from.Task.Wait에서.NET 월드.


편집: 제품에서 관련 질문에 대한 다른 답변을 위해 이 코드를 제거했습니다.

때때로 이벤트 루프가 그곳에 있고 실행 중입니다.이 경우 다시 실행할 필요가 없습니다. create_task를 사용하여 작업을 생성하면 됩니다.

이것을 먹어보세요.

try:
    loop = asyncio.get_event_loop()
except RuntimeError:
    loop = asyncio.new_event_loop()
    asyncio.set_event_loop(loop)
        
task = loop.create_task(user_insert_events(target))
if not loop.is_running():
    loop.run_until_complete(task)

언급URL : https://stackoverflow.com/questions/46827007/runtimeerror-this-event-loop-is-already-running-in-python

반응형