在python中同时运行交互功能

时间:2017-11-04 14:41:51

标签: python python-3.x python-multiprocessing python-multithreading

所以我试图建立一个可以自主驾驶的机器人。为此,我需要机器人前进并同时检查距离。如果距离小于首选距离,则停止向前移动。到目前为止,我已经在下面编写了这段代码,但它似乎并没有同时运行,而且它们也没有进行交互。我怎样才能确保这两个函数确实相互作用。如果还有需要的信息,我很乐意为您提供。谢谢!

from multiprocessing import Process
from TestS import distance
import Robot
import time

constant1 = True
min_distance = 15

def forward():
    global constant1:
    robot.forward(150)                       #forward movement, speed 150
    time.sleep(2)

def distance_check():
    global constant1
    while constant1:
        distance()                           #checking distance
        dist = distance()
        return dist
        time.sleep(0.3)

        if dist < min_distance:
            constant1 = False
            print 'Something in the way!'
            break

def autonomy():                              #autonomous movement
    while True:
        p1 = Process(target=forward)         
        p2 = Process(target=distance_check)
        p1.start()                           #start up 2 processes
        p2.start()
        p2.join()                            #wait for p2 to finish

2 个答案:

答案 0 :(得分:2)

因此,您发布的代码存在一些严重问题。首先,您不希望distance_check进程完成,因为它正在运行while循环。您不应该p2.join(),也不应该在while循环中始终启动新进程。你在这里混合了太多的做事方式 - 要么两个孩子永远奔跑,要么他们每个人跑一次,而不是混合。

然而,主要问题是原始流程无法与原始流程进行通信,即使是通过global (除非您做更多工作)。线程更适合这个问题。

您的return函数中还有一个distance_check(),因此该语句下方的代码无法执行(包括sleepconstant1的设置{1}}(应该有更好的名字)。

总之,我认为你想要这样的东西:

from threading import Thread
from TestS import distance
import Robot
import time

can_move_forward = True
min_distance = 15


def move_forward():
    global can_move_forward
    while can_move_forward:
        robot.forward(150)
        time.sleep(2)
        print('Moving forward for two seconds!')


def check_distance():
    global can_move_forward
    while True:
        if distance() < min_distance:
            can_move_forward = False
            print('Something in the way! Checking again in 0.3 seconds!')
        time.sleep(0.3)


def move_forward_and_check_distance():
    p1 = Thread(target = move_forward)
    p2 = Thread(target = check_distance)
    p1.start()
    p2.start()

由于您在代码中指定了python-3.x,我们还更正了您的print

显然我无法检查这是否会按照您的意愿运行,因为我没有您的机器人,但我希望这至少对您有所帮助。

答案 1 :(得分:2)

多处理解决方案的一个问题是distance_check返回停止

    dist = distance()
    return dist        # <------ 
    time.sleep(0.3)

    if dist < min_distance:
        ....

您似乎正在尝试在流程之间交换信息:通常使用Queues or Pipes完成。

在您的问题的行之间阅读并提出以下规范:

  • 机器人在速度大于零时移动
  • 不断检查机器人前方的障碍物
  • 如果机器人接近某物就停止它。

我认为您可以在不使用多处理的情况下实现目标。这是一个使用生成器/协同程序的解决方案。

出于测试目的,我编写了自己的机器人版本和障碍物传感器 - 试图模仿我在代码中看到的内容

class Robot:
    def __init__(self, name):
        self.name = name
    def forward(self, speed):
        print('\tRobot {} forward speed is {}'.format(self.name, speed))
        if speed == 0:
            print('\tRobot {} stopped'.format(speed))

def distance():
    '''User input to simulate obstacle sensor.'''
    d = int(input('distance? '))
    return d

Decorator to start a coroutine/generator

def consumer(func):
    def wrapper(*args,**kw):
        gen = func(*args, **kw)
        next(gen)
        return gen
    wrapper.__name__ = func.__name__
    wrapper.__dict__ = func.__dict__
    wrapper.__doc__  = func.__doc__
    return wrapper

生产者不断检查是否可以安全移动

def can_move(target, min_distance = 15):
    '''Continually check for obstacles'''
    while distance() > min_distance:
        target.send(True)
        print('check distance')
    target.close()

消耗安全移动信号的生成器/协程,并根据需要更改机器人的速度。

@consumer
def forward():
    try:
        while True:
            if (yield):
                robot.forward(150)
    except GeneratorExit as e:
        # stop the robot
        robot.forward(0)

机器人的速度应该与障碍物传感器产生距离一样快。机器人将向前移动直到它接近某个东西然后停止并且所有关闭。通过在forwardcan_move中稍微调整逻辑,您可以更改行为,以便生成器/协同程序继续运行,但只要有一些东西在它前面就会发送零速命令走开(或机器人转动)它会再次开始移动。

用法:

>>> 
>>> robot = Robot('Foo')
>>> can_move(forward())
distance? 100
    Foo forward speed is 150
check distance
distance? 50
    Foo forward speed is 150
check distance
distance? 30
    Foo forward speed is 150
check distance
distance? 15
    Foo forward speed is 0
    Robot 0 stopped
>>>

虽然这在Python 3.6中有效,但它基于对生成器和协同程序的可能过时的概念/理解。使用Python 3 +的一些async添加可能有不同的方法。