Python Asyncio永远运行_()和任务

Python Asyncio永远运行_()和任务,python,google-cloud-platform,python-asyncio,Python,Google Cloud Platform,Python Asyncio,我将此代码改编为在异步Python中使用Google Cloud PubSub: 我基本上删除了发布代码,只使用订阅代码。 但是,最初我没有包括loop.create_taskmessage_生产者行。我认为任务是按照预期的方式创建的,但它们从来没有实际运行过。只有当我添加上述行时,代码才能正确执行,所有创建的任务才能运行。是什么导致了这种行为 PubSub正在从其他线程调用create_proc_message_任务回调。由于create_任务是,因此只能从运行事件循环(通常是主线程)的线程调

我将此代码改编为在异步Python中使用Google Cloud PubSub:

我基本上删除了发布代码,只使用订阅代码。 但是,最初我没有包括loop.create_taskmessage_生产者行。我认为任务是按照预期的方式创建的,但它们从来没有实际运行过。只有当我添加上述行时,代码才能正确执行,所有创建的任务才能运行。是什么导致了这种行为

PubSub正在从其他线程调用create_proc_message_任务回调。由于create_任务是,因此只能从运行事件循环(通常是主线程)的线程调用它。要更正此问题,请将loop.create\u taskproc\u messagemessagemessage替换为asyncio.run\u corroutine\u threadsafeproc\u messagemessage,不再需要循环和消息生成器

至于为什么MexAgEngIsPug出现修复代码,考虑这两个额外的事情比CealTyTask:

它以线程安全的方式运行,因此当同时执行此操作时,事件循环数据结构不会损坏。 它确保事件循环在尽可能快的时间内唤醒,以便它能够处理新任务。
在您的例子中,create_task将任务添加到循环的可运行队列中,但没有任何锁定,但未能确保唤醒,因为在事件循环线程中运行时不需要这样做。然后,消息生成器强制循环定期唤醒,这也是它检查并执行可运行任务的时候。

听起来好像PubSub正在从另一个线程调用create\u proc\u message\u task回调。将loop.create_taskproc_messagemessagemessage替换为asyncio.run_coroutine_threadsafeproc_messagemessage,循环和其他操作应该可以正常工作,而不会生成消息\u producer。这就成功了!非常感谢。你能详细说明一下这里发生了什么事吗?假设你的假设是正确的,那么为什么消息制作人会解决这个问题呢?我现在发布了一个答案,并给出了更详细的解释。无意中从不同线程调用asyncio是一个非常常见的错误。
import asyncio
import datetime
import functools
import os

from google.cloud import pubsub
from google.gax.errors import RetryError
from grpc import StatusCode

async def message_producer():
    """ Publish messages which consist of the current datetime """
    while True:
        await asyncio.sleep(0.1)


async def proc_message(message):
    await asyncio.sleep(0.1)
    print(message)
    message.ack()


def main():
    """ Main program """
    loop = asyncio.get_event_loop()

    topic = "projects/{project_id}/topics/{topic}".format(
        project_id=PROJECT, topic=TOPIC)
    subscription_name = "projects/{project_id}/subscriptions/{subscription}".format(
        project_id=PROJECT, subscription=SUBSCRIPTION)

    subscription = make_subscription(
        topic, subscription_name)

    def create_proc_message_task(message):
        """ Callback handler for the subscription; schedule a task on the event loop """
        print("Task created!")
        task = loop.create_task(proc_message(message))

    subscription.open(create_proc_message_task)
    # Produce some messages to consume

    loop.create_task(message_producer())

    print("Subscribed, let's do this!")
    loop.run_forever()


def make_subscription(topic, subscription_name):
    """ Make a publisher and subscriber client, and create the necessary resources """
    subscriber = pubsub.SubscriberClient()
    try:
        subscriber.create_subscription(subscription_name, topic)
    except:
        pass
    subscription = subscriber.subscribe(subscription_name)

    return subscription


if __name__ == "__main__":
    main()