Kivy 异步任务

如果要进行一些非常耗时的操作(例如:爬虫等),那么页面就会在这里卡住,而系统就会以为这个软件无响应,并提示关闭,可以说明用户体验极差,因此我们在此处引入异步操作。

        在py中引入事件调节器,并在处理具体业务逻辑的异步方法async def pulse里让程序休眠两分钟。

pythonProject6\MRWord\asynico_task\asynico_insert_date.py

import asyncio
import threading
import logging
from kivy.event import EventDispatcher
class EventLoopWorker(EventDispatcher):

    # 定义唯一事件
    __events__ = ('on_pulse',)

    def __init__(self, file_path, **kwargs):
        super().__init__(**kwargs)
        # 制定目标
        self._thread = threading.Thread(target=self._run_loop)
        self._thread.daemon = True
        self.loop = None
        self._pulse = None
        self._pulse_task = None
        self.src = file_path

    def _run_loop(self):
        self.loop = asyncio.get_event_loop_policy().new_event_loop()
        asyncio.set_event_loop(self.loop)
        self._restart_pulse()
        self.loop.run_forever()

    def start(self):
        self._thread.start()

    async def pulse(self):
        """ 处理具体业务逻辑 """
        import time
        logging.info("Upload is ready, filepath is %s" % self.src)
        # 休眠两分钟
        time.sleep(120)
        logging.info("Upload shutdown")
        self.__init__(self.src)

    def _restart_pulse(self):
        """ 启动或重置任务 """
        if self._pulse_task is not None:
            self._pulse_task.cancel()
        self._pulse_task = self.loop.create_task(self.pulse())

    def on_pulse(self, *_):
        """ EventDispatcher 事件必须添加的方法 """
        pass
0  events = (‘on_pulse’,) 是什么作用,可以删除吗

在这个代码中,__events__ = ('on_pulse',) 是一个类变量,它定义了该类所支持的事件。在这个例子中,EventLoopWorker 类支持一个名为 on_pulse 的事件。

这个类变量的作用是为了方便其他代码使用该类时能够知道可以触发哪些事件。通过定义 __events__ 变量,其他开发者可以清楚地知道该类支持哪些事件,并可以根据需要进行相应的处理。

如果你不需要使用 on_pulse 事件,你可以删除 __events__ = ('on_pulse',) 这行代码。但是请注意,如果其他代码依赖于该事件,删除这行代码可能会导致其他部分的功能出现问题。

1  _pulse 和_pulse_task  是什么

在这个EventLoopWorker类中,_pulse_pulse_task都是实例属性。其中_pulse是一个标记,用于指示工作线程是否应该停止执行任务并退出。而_pulse_task则是定时任务,用于触发on_pulse事件。当_pulse为True时,工作线程会在下一次循环时退出。

在此之前,需要说明一下EventDispatcher是什么。EventDispatcher是一个事件调度器,可以用来注册、分发和处理事件。EventLoopWorker继承了EventDispatcher,并定义了自己的唯一事件on_pulse。在_run_loop方法中,每隔一段时间就会触发on_pulse事件,这个事件会被注册的回调函数所处理。

src是传入的参数,表示工作线程需要处理的目标文件路径。

2  asyncio 是什么

asyncio — Asynchronous I/O — Python 3.12.3 documentation

asyncio是Python的标准库之一,它是一种基于协程的异步IO编程库。通过使用asyncio可以方便地编写高效的异步IO程序,避免了多线程或多进程编程的复杂性和开销。asyncio提供了事件循环、任务、协程、回调、异步IO等功能,可以用于编写高效的网络应用、Web框架、爬虫等。

在上述代码中,asyncio.get_event_loop_policy()获取事件循环的策略,并且创建了一个新的事件循环loop,接着将新的事件循环设置为当前的事件循环,最后启动了事件循环。

asyncio.get_event_loop_policy() 是一个函数,它返回当前事件循环策略的实例。在 asyncio 中,事件循环负责协程的调度和管理,而事件循环策略则是事件循环的实现机制。asyncio.get_event_loop_policy() 返回的是一个策略对象,可以通过该对象创建、获取、设置事件循环。

在默认情况下,asyncio 会使用 asyncio.DefaultEventLoopPolicy() 策略来创建事件循环,但是在某些情况下,我们可能需要使用其他的策略来实现事件循环。

asyncio.get_event_loop_policy()是一个函数,它返回当前事件循环策略的实例。事件循环策略用于管理asyncio事件循环的行为和属性。在Python 3.7之前,asyncio只支持单个事件循环策略,但是在Python 3.7中,可以通过实现自定义事件循环策略来管理多个事件循环。get_event_loop_policy()函数返回的实例可以用于获取和修改事件循环策略的行为和属性。

关于循环策略实例,它通常包含以下属性和方法:

  • asyncioloop:获取当前事件循环策略的事件循环实例。
  • set_event_loop:将指定的事件循环设置为当前循环策略的事件循环。
  • get_child_watcher:获取当前事件循环策略的子进程监视器实例。
  • set_child_watcher:将指定的子进程监视器设置为当前循环策略的子进程监视器。
  • get_exception_handler:获取当前事件循环策略的异常处理函数。
  • set_exception_handler:将指定的异常处理函数设置为当前循环策略的异常处理函数。
  • get_name:获取当前事件循环策略的名称。
3 asyncio.get_event_loop_policy()是一个函数,它返回当前事件循环策略的实例是什么样子的?请给出一个实例参考一下

asyncio.get_event_loop_policy()是一个函数,它返回当前事件循环策略的实例。在Python 3.10中,asyncio的默认策略将更改为ProactorEventLoopPolicy,而在之前的版本中,默认策略为SelectorEventLoopPolicy。

下面是一个使用SelectorEventLoopPolicy策略的示例:

import asyncio

loop = asyncio.get_event_loop()
print(type(loop))

输出结果为:

<class 'asyncio.selector_events.SelectorEventLoop'>
 请给出一个使用asyncio.get_event_loop_policy() 的具体案例学习

asyncio.get_event_loop_policy() 是用于获取异步事件循环策略的函数。它返回一个事件循环策略对象,可以使用该对象来创建事件循环。

以下是一个使用 asyncio.get_event_loop_policy() 的具体案例,用于创建异步事件循环和运行协程:

import asyncio

async def coroutine():
    print('This is a coroutine.')

loop = asyncio.get_event_loop_policy().get_event_loop()
loop.run_until_complete(coroutine())

上面的代码中,我们定义了一个协程 coroutine(),然后通过 asyncio.get_event_loop_policy() 获取了默认的事件循环策略对象,并使用 get_event_loop() 方法创建了事件循环。最后,通过调用 run_until_complete() 方法运行协程。

4 loop.create_task()

create_task() 是 asyncio 包中的一个方法,用于创建一个协程任务并将其添加到事件循环中。该方法的作用是将协程转化为一个 task 对象,并加入到事件循环中,使其被调度运行。

在你提供的代码中,create_task() 方法用于创建一个协程任务并将其添加到事件循环中,其中 self.pulse() 是一个协程函数,用于进行心跳检测。这样就可以通过 asyncio 事件循环的机制,自动运行心跳检测协程。

需要注意的是,使用 create_task() 方法创建的任务是非阻塞的,即异步执行,不会阻塞当前线程。同时,在协程运行完成后,会自动返回一个 future 对象,可以通过该对象获取协程运行的结果或状态。

5 loop.call_soon()

loop.call_soon() 是 asyncio 的一个方法,用于将一个回调函数添加到事件循环中。当事件循环运行时,该回调函数会被执行。它的作用是将任务放入事件循环中,等待事件循环调度执行。此方法返回一个 asyncio.Handle 对象,它可以用来取消该回调函数的执行。

具体来说,当我们想要在 asyncio 中执行一些异步操作时,可以使用 loop.call_soon() 方法将这些操作封装成一个协程,然后添加到事件循环中。一旦事件循环开始运行,这些协程就会按照添加的顺序依次执行。

举个例子,如果我们想要在 asyncio 中发起一个 HTTP 请求,可以使用 aiohttp 库提供的异步请求方法,并将其封装成一个协程。然后使用 loop.call_soon() 方法将该协程添加到事件循环中,等待事件循环调度执行。

6 loop.call_later

loop.call_later() 是 Python 中 asyncio 的方法之一,它允许您安排在指定时间之后执行的回调函数。具体来说,它将在事件循环中安排一个定时器,并在定时器触发时执行指定的回调函数。

使用 loop.call_later() 可以很方便地处理一些需要在一段时间之后才能处理的任务,例如在等待某些资源可用时进行轮询。

下面是使用 loop.call_later() 的一个简单示例:

import asyncio

async def hello():
    print("Hello")
    await asyncio.sleep(1)
    print("World")

def say_hello_later(loop):
    loop.create_task(hello())

loop = asyncio.get_event_loop()
loop.call_later(2, say_hello_later, loop)
loop.run_forever()

以上代码将会在 2 秒钟后输出 “Hello”,然后等待 1 秒钟再输出 “World”。

Event Loop — Python 3.12.3 documentation

        loop.call_later() 的执行顺序如何保证?

在 Python 的 asyncio 模块中,loop.call_later() 是一种在指定时间后调用指定函数的方式。它的执行顺序是由事件循环机制来保证的,即当我们使用 loop.call_later() 注册一个任务时,事件循环会将该任务放到一个任务队列中。然后,事件循环会不断地从任务队列中获取任务并执行,直到队列为空或者事件循环被关闭。

需要注意的是,loop.call_later() 注册的任务并不会立即执行,而是在指定的时间后才会执行。如果多个任务的执行时间相同,则它们的执行顺序是随机的,但是如果它们的执行时间不同,则会按照执行时间从小到大的顺序执行。

7 loop = asyncio.get_event_loop()

loop = asyncio.get_event_loop() 是一个创建一个事件循环的方法。asyncio是Python中用于异步编程的库,它提供了一种基于事件循环的异步模型,能够帮助我们更加高效地处理I/O密集型任务。在使用asyncio时,我们需要创建一个事件循环,然后将任务添加到事件循环中执行,通过future对象来获取任务的执行结果。get_event_loop() 方法就是用来创建事件循环的,它会返回当前线程的事件循环实例,如果当前线程没有事件循环实例,则会自动创建一个。一般来说,在使用asyncio时都需要先创建一个事件循环,再将任务添加到事件循环中执行。

8 threading.Thread.start()

threading.Thread.start() 是 Python 中的一个方法,它用于启动一个新的线程,并让这个线程开始执行。这个方法会在后台创建一个新的线程,并调用线程的 run() 方法,在这个方法中定义线程要执行的任务。

需要注意的是,start() 方法只能在一个 Thread 实例中调用一次,否则会抛出 RuntimeError 异常。

以下是一个简单的示例:

import threading

def my_func():
    print("Hello, world!")

my_thread = threading.Thread(target=my_func)
my_thread.start()
9  self._pulse_task.cancel() 中.cancle()

cancel() 方法用于取消一个正在进行的任务。在本例中,self._pulse_task.cancel() 方法用于取消正在进行的 _pulse_task 任务,以便能够重新启动或重置任务。当任务被取消时,它不会再继续执行,并且会返回一个布尔值,表明任务是否已经被取消。如果任务尚未执行,那么它将不会被执行,也不会返回任何值。需要注意的是,一旦任务被取消,它就不能再次被启动或者执行。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

xinzheng新政

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值