在无限打印的背景下进行asyncio轮询

时间:2018-01-07 19:01:38

标签: python multithreading python-asyncio

我想在Python中使用基本的想法:

假设我对一个读取当前汽车速度的函数进行了阻塞调用(我使用python-can,并等待相应的消息出现在总线上)。

另一方面,我有一个无限循环,尽可能精确地打印汽车的速度。

我想要的是直接更新速度的值,以便无限循环可以在变化时立即打印出来。

现在我有三个想法:

  • 在循环中调用我的get_speed函数,然后阻止。这是有效的,但只有这是我愿意打印的唯一值(剧透警报:它不是)。如果我也想精确打印RPM,我必须等待找到速度,之前可能会丢失多个RPM值。
  • 创建另一个更新全局变量的“线程”(子进程/多处理/线程,无论你怎么称呼它)。我知道这有效,但是,我觉得我可以有更聪明的东西
  • 从我在javascript中看到的,有一种方法可以向函数询问结果,并继续运行直到找到这个结果(这现在响起了一些CPU铃声)。我有点想要这样的东西,这可以让我做到以下
speed = get_speed()
rpm = get_rpm()

while True:
        print("RPM: {0} - Speed: {1}".format(rpm, speed))

这会(在我的童话世界中)实际显示如下:

RPM: None - Speed: None  # Function haven't returned yet, waiting
RPM: None - Speed: None  # Same here
RPM: None - Speed: None  # Same here
RPM: 300 - Speed: None   # get_rpm has returned
RPM: 300 - Speed: None   # Nothing happened
RPM: 303 - Speed: 0      # get_rpm and get_speed have returned
RPM: 303 - Speed: 0
RPM: 312 - Speed: 0      # etc.

现在我拥有的是这样的东西,它根本不起作用

#!/usr/bin/env python3

import datetime
import asyncio
import random
from time import sleep

async def _can_get_speed():
    # My long function
    print ("In   can_get_speed")
    sleep(4)
    print ("Out  can_get_speed")
    r = random.randint(0, 10)
    print(r)
    return r

async def can_get_speed():
    return await asyncio.gather(_can_get_speed())

if __name__ == "__main__":
    loop = asyncio.get_event_loop()
    speed = 0
    speed = loop.call_soon(can_get_speed, loop)
    loop.run_forever()


    while True:
        print("Speed: {0}".format(speed))

我的两个问题是:

  1. 这是最正确的方法( - > asyncio,我的意思),和 如果不是什么?
  2. 如果是,有人可以帮助我理解 asyncio更好:))
  3. 提前致谢!

1 个答案:

答案 0 :(得分:0)

我能够得到这样的预期结果:

#!/usr/bin/env python3

import datetime
import asyncio
import random
from time import sleep
from multiprocessing import Process, Queue

def can_get_speed(q):
    while True:
        print("IN get_speed")
        r = random.randint(1, 4)
        sleep(r)
        print("Return {0}".format(r))
        q.put(r)

def can_get_rpm(q):
    while True:
        print("IN get_rpm")
        r = random.randint(1, 4)
        sleep(r)
        print("Return {0}".format(r))
        q.put(r)


if __name__ == "__main__":

    q = Queue()
    q2 = Queue()

    p = Process(target=can_get_speed, args=(q,))
    p2 = Process(target=can_get_rpm, args=(q2,))

    p.start()
    p2.start()

    speed = None
    rpm = None

    while True:
        if not q.empty():
            speed = q.get()
        if not q2.empty():
            rpm = q2.get()

        print("Speed: {0} - RPM: {1} - {2}".format(speed, rpm, datetime.datetime.now()))

有更聪明的方法吗?