Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/331.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python pyzmq REQ/REP,带有异步IO等待变量_Python_Zeromq_Distributed Computing_Python Asyncio_Req - Fatal编程技术网

Python pyzmq REQ/REP,带有异步IO等待变量

Python pyzmq REQ/REP,带有异步IO等待变量,python,zeromq,distributed-computing,python-asyncio,req,Python,Zeromq,Distributed Computing,Python Asyncio,Req,我第一次在python中使用asyncio,并尝试将其与ZMQ结合起来 基本上,我的问题是我有一个REP/REQ系统,在一个async def中,有一个我需要等待的函数。如何不更新该值。 下面是一段代码来说明: #Declaring the zmq context context = zmq_asyncio.Context() REP_server_django = context.socket(zmq.REP) REP_server_django.bind("tcp://*:5558") 我

我第一次在python中使用asyncio,并尝试将其与ZMQ结合起来

基本上,我的问题是我有一个REP/REQ系统,在一个
async def
中,有一个我需要等待的函数。如何不更新该值。 下面是一段代码来说明:

#Declaring the zmq context
context = zmq_asyncio.Context()
REP_server_django = context.socket(zmq.REP)
REP_server_django.bind("tcp://*:5558")
我将这个对象发送给一个类,并在这个函数中获取它

async def readsonar(self, trigger_pin, REP_server_django):
        i= 0
        while True:

            ping_from_view = await REP_server_django.recv()  # line.1
            value = await self.board.sonar_read(trigger_pin) # line.2
            print(value)                                     # line.3
            json_data = json.dumps(value)                    # line.4
            #json_data = json.dumps(i)                       # line.4bis
            REP_server_django.send(json_data.encode())       # line.5
            i+=1                                             # line.6
            await asyncio.sleep(1/1000)                      # line.7
声纳读取正在使用pymata\u express读取超声波传感器。如果我对
行.2
行.4
进行注释,我会得到
I
的正确值。如果我评论
行.1
行.5
打印(值)
声纳读取打印正确的值。但是,当我如图所示运行它时,
值不会更新

我错过什么了吗


编辑:
编辑了有关行注释的类型。我的意思是,如果我只读取声纳并打印数值。它很好用。如果我只使用
.recv()
.send(json.dumps(I).encode())
,它就可以工作。但是如果我试着从声纳发送数据。它锁定到未更新的给定值


EDIT2:(对艾伦·约林克斯的回答):这是MWE,它考虑了您在课堂上发送的关于
zmq
声明的内容。它取自
pymata_express
示例

要再现错误,请在两个不同的终端中运行这两个脚本。您需要安装一个arduino板。如果一切顺利,
第A部分。
只应在
mve_req.py
末尾吐出相同的值。您可以编辑不同的块(A、B或C部分)以查看其行为

mve_代表py

#ADAPTED FROM PYMATA EXPRESS EXAMPLE CONCURRENTTAKS
#https://github.com/MrYsLab/pymata-express/blob/master/examples/concurrent_tasks.py
import asyncio
import zmq
import json
import zmq.asyncio as zmq_asyncio
from pymata_express.pymata_express import PymataExpress


class ConcurrentTasks:

    def __init__(self, board):


        self.loop = board.get_event_loop()
        self.board = board

        self.ctxsync = zmq.Context()
        self.context = zmq.asyncio.Context()
        self.rep = self.context.socket(zmq.REP)
        self.rep.bind("tcp://*:5558")

        self.trigger_pin = 53
        self.echo_pin = 51

        loop.run_until_complete(self.async_init_and_run())

    async def readsonar(self):
        i = 0
        while True:


            #PART. A. WHAT I HOPE COULD WORK
            rep_recv = await self.rep.recv()                       # line.1
            value = await self.board.sonar_read(self.trigger_pin)  # line.2
            print(value)                                           # line.3
            json_data = json.dumps(value)                          # line.4
            # json_data = json.dumps(i)                            # line.4bis
            await self.rep.send(json_data.encode())                # line.5
            i += 1                                                 # line.6
            await asyncio.sleep(1 / 1000)                          # line.7


            '''
            #PART. B. WORKS FINE IN UPDATING THE SONAR_RAED VALUE AND PRINTING IT
            value = await self.board.sonar_read(self.trigger_pin)  # line.2
            print(value)                                           # line.3
            json_data = json.dumps(value)                          # line.4
            i += 1                                                 # line.6
            await asyncio.sleep(1 / 1000)                          # line.7
            '''

            '''
            #PART. C. WORKS FINE IN SENDING THE i VALUE OVER ZMQ
            rep_recv = await self.rep.recv()                       # line.1
            json_data = json.dumps(i)                              # line.4bis
            await self.rep.send(json_data.encode())                # line.5
            i += 1                                                 # line.6
            await asyncio.sleep(1 / 1000)                          # line.7
            '''



    async def async_init_and_run(self):

        await self.board.set_pin_mode_sonar(self.trigger_pin, self.echo_pin)

        readsonar = asyncio.create_task(self.readsonar())
        await readsonar

        # OTHER CREATED_TASK GO HERE, (removed them in the MVE, but they work fine)


if __name__ == "__main__":
    loop = asyncio.get_event_loop()
    my_board = PymataExpress()
    try:
        ConcurrentTasks(my_board)
    except (KeyboardInterrupt, RuntimeError):
        loop.run_until_complete(my_board.shutdown())
        print('goodbye')
    finally:
        loop.close()
import zmq
import time
import json

def start_zmq():
    context = zmq.Context()
    REQ_django  = context.socket(zmq.REQ)
    REQ_django.connect("tcp://localhost:5558")

    return REQ_django, context

def get_sonar(REQ_django):
    REQ_django.send(b"server_django")
    ping_from_server_django = REQ_django.recv()
    return ping_from_server_django.decode()

if __name__ == '__main__':

    data = {"sensors":{}}

    REQ_django, context = start_zmq()
    while REQ_django:

            data['sensors']['sonar'] = get_sonar(REQ_django)
            json_data = json.dumps(data)
            print(data)

            #DO OTHER WORK
            time.sleep(1)

    REQ_django.close()
    context.term()
mve_要求py

#ADAPTED FROM PYMATA EXPRESS EXAMPLE CONCURRENTTAKS
#https://github.com/MrYsLab/pymata-express/blob/master/examples/concurrent_tasks.py
import asyncio
import zmq
import json
import zmq.asyncio as zmq_asyncio
from pymata_express.pymata_express import PymataExpress


class ConcurrentTasks:

    def __init__(self, board):


        self.loop = board.get_event_loop()
        self.board = board

        self.ctxsync = zmq.Context()
        self.context = zmq.asyncio.Context()
        self.rep = self.context.socket(zmq.REP)
        self.rep.bind("tcp://*:5558")

        self.trigger_pin = 53
        self.echo_pin = 51

        loop.run_until_complete(self.async_init_and_run())

    async def readsonar(self):
        i = 0
        while True:


            #PART. A. WHAT I HOPE COULD WORK
            rep_recv = await self.rep.recv()                       # line.1
            value = await self.board.sonar_read(self.trigger_pin)  # line.2
            print(value)                                           # line.3
            json_data = json.dumps(value)                          # line.4
            # json_data = json.dumps(i)                            # line.4bis
            await self.rep.send(json_data.encode())                # line.5
            i += 1                                                 # line.6
            await asyncio.sleep(1 / 1000)                          # line.7


            '''
            #PART. B. WORKS FINE IN UPDATING THE SONAR_RAED VALUE AND PRINTING IT
            value = await self.board.sonar_read(self.trigger_pin)  # line.2
            print(value)                                           # line.3
            json_data = json.dumps(value)                          # line.4
            i += 1                                                 # line.6
            await asyncio.sleep(1 / 1000)                          # line.7
            '''

            '''
            #PART. C. WORKS FINE IN SENDING THE i VALUE OVER ZMQ
            rep_recv = await self.rep.recv()                       # line.1
            json_data = json.dumps(i)                              # line.4bis
            await self.rep.send(json_data.encode())                # line.5
            i += 1                                                 # line.6
            await asyncio.sleep(1 / 1000)                          # line.7
            '''



    async def async_init_and_run(self):

        await self.board.set_pin_mode_sonar(self.trigger_pin, self.echo_pin)

        readsonar = asyncio.create_task(self.readsonar())
        await readsonar

        # OTHER CREATED_TASK GO HERE, (removed them in the MVE, but they work fine)


if __name__ == "__main__":
    loop = asyncio.get_event_loop()
    my_board = PymataExpress()
    try:
        ConcurrentTasks(my_board)
    except (KeyboardInterrupt, RuntimeError):
        loop.run_until_complete(my_board.shutdown())
        print('goodbye')
    finally:
        loop.close()
import zmq
import time
import json

def start_zmq():
    context = zmq.Context()
    REQ_django  = context.socket(zmq.REQ)
    REQ_django.connect("tcp://localhost:5558")

    return REQ_django, context

def get_sonar(REQ_django):
    REQ_django.send(b"server_django")
    ping_from_server_django = REQ_django.recv()
    return ping_from_server_django.decode()

if __name__ == '__main__':

    data = {"sensors":{}}

    REQ_django, context = start_zmq()
    while REQ_django:

            data['sensors']['sonar'] = get_sonar(REQ_django)
            json_data = json.dumps(data)
            print(data)

            #DO OTHER WORK
            time.sleep(1)

    REQ_django.close()
    context.term()
(O/p MCVE问题的定义更进一步——然而,{sensors | actors}控制系统的协调问题,无论优先与否,使用分布式自治代理设计的系统在专业上越复杂,就越容易产生有缺陷的“捷径”或陷入困境 最好在不到五秒钟的时间内首先阅读层次结构和关于相互死锁阻塞

阅读Pieter HINTJENS的精彩著作《连接的代码:第1卷》对任何系统设计师都具有巨大的价值)

“…非常有趣,因为它已经实现了异步,所以我可以像以前一样添加异步zmq。我错了吗?”

是的,没有“只添加异步”的快捷方式,控制系统是非常有趣的学科,而是一个复杂的学科。总是。很抱歉不得不直说。一些复杂性可能在教科书示例或琐碎的项目中对用户隐藏。然后,通过添加一个或几个更为琐碎的功能,锤子就可以尝试扩展它们。复杂性突然浮出水面,这是以前从未见过的


O/P多代理的正式映射-
[A、B、C、D]
-系统代码(原样) 将正式地图放在一个全屏编辑器上,以便看到所有相互冲突的依赖关系和相互竞争的控制循环的大图。延迟是最简单的部分。无法解决的死锁阻塞风险的几个地方是核心。ZeroMQ,因为v2.x有避免其中一些问题的工具,所以软件设计师有责任适当地缓解所有其他问题。控制系统(机器人或其他)必须证明这种鲁棒性和对错误的恢复能力,并安全地“生存”所有“外部”事故

最好从第1行汇编语言指令中表达的旧黄金法则开始:

;ASSUME NOTHING
并努力仔细设计其余的部分


并运行一系列100个声纳测试,以获得潜伏期的最小值、平均值、标准差、最大值读数,所有这些读数都在
[us]
中,因为这些值是最基本的,以防设计一些控制回路时不考虑声纳传感器数据

[ aFun( [ sonarBeep()[1] for _    in range( 100 ) ]
        )                for aFun in ( np.min, np.mean, np.std, np.max )
  ]
系统架构和子系统协调: 最后,但并非最不重要的一点是,可以在一个绝对独立的事件循环中读取和存储声纳数据,与任何其他操作不协调,只从这样的存储中读取一个状态变量,设置在一个独立工作的子系统中(如果作为独立的系统行为这样做不会极大地节省电源的话)

每当人们试图紧密地协调独立事件流时(在具有不协调或弱协调代理的分布式系统中最糟糕的情况),设计必须增强对错误和时间错误对齐的鲁棒性以及错误恢复能力。否则,系统可能很快就会死锁/活锁

如果有疑问,可以学习施乐帕洛阿尔托研究中心MVC分离的最初理念,
模型的
部分可以(并且大部分时间在GUI框架中,自198x+以来)接收许多独立于其他系统组件更新的状态变量,只要读取/使用实际状态变量的数据就可以了。类似地,如果功率预算允许,声纳可以连续扫描场景并将读数写入任何本地寄存器,并让其他组件来请求或获得最后一次实际声纳读数的请求

ZeroMQ zen也是如此

如果这可能有帮助,请检查本地侧消息存储的
zmq.CONFLATE
模式是否按此方式工作


一个小提示:有人可能已经注意到,
sleep(1/1000)
是一个非常昂贵、重复执行的步骤,而且非常危险,因为在py2.x中,由于整数除法,它实际上不会休眠。

我不确定这是否能解决您的问题,但我确实发现了一些潜在的问题

  • 目前尚不清楚readsonar的使用情况
    import asyncio
    import zmq
    import json
    
    
    class Play:
        def __init__(self):
            self.context = zmq.asyncio.Context()
            self.REP_server_django = self.context.socket(zmq.REP)
            self.REP_server_django.bind("tcp://*:5558")
            self.event_loop = asyncio.get_event_loop()
            self.event_loop.run_until_complete(self.readsonar(4))
    
        async def readsonar(self, trigger_pin):
            i = 0
            while True:
                ping_from_view = await self.REP_server_django.recv()  # l.1
                value = await self.board.sonar_read(trigger_pin)  # l.2
                print(value)  # l.3
                json_data = json.dumps(value)  # l.4
                # json_data = json.dumps(i) # l.4bis
                await self.REP_server_django.send(json_data.encode())  # l.5
                i += 1  # l.6
                await asyncio.sleep(1 / 1000)  # l.6
    
    #ADAPTED FROM PYMATA EXPRESS EXAMPLE CONCURRENTTAKS
    #https://github.com/MrYsLab/pymata-express/blob/master/examples/concurrent_tasks.py
    import asyncio
    import zmq
    import json
    import zmq.asyncio as zmq_asyncio
    from pymata_express.pymata_express import PymataExpress
    
    
    class ConcurrentTasks:
    
        def __init__(self, board):
    
    
            self.loop = board.get_event_loop()
            self.board = board
    
            self.ctxsync = zmq.Context()
            self.context = zmq.asyncio.Context()
            self.rep = self.context.socket(zmq.REP)
            self.rep.bind("tcp://*:5558")
    
            self.trigger_pin = 53
            self.echo_pin = 51
    
            loop.run_until_complete(self.async_init_and_run())
    
        ### START:  NEW CODE THAT RESOLVED THE ISSUE
        async def pingsonar(self):
            value = await self.board.sonar_read(self.trigger_pin)
            return value
    
        async def readsonar(self):
            while True:
                rep_recv = await self.rep.recv() 
                value = await asyncio.wait([self.pingsonar()])
                valuesonar = list(value[0])[0].result()
                json_data = json.dumps(valuesonar) 
                await self.rep.send(json_data.encode()) 
                await asyncio.sleep(1 / 1000) #maybe this line isn't necessary
    
        ### END : NEW CODE THAT RESOLVED THE ISSUE
    
        async def async_init_and_run(self):
    
            await self.board.set_pin_mode_sonar(self.trigger_pin, self.echo_pin)
    
            readsonar = asyncio.create_task(self.readsonar())
            await readsonar
    
            # OTHER CREATED_TASK GO HERE, (removed them in the MVE, but they work fine)
    
    
    if __name__ == "__main__":
        loop = asyncio.get_event_loop()
        my_board = PymataExpress()
        try:
            ConcurrentTasks(my_board)
        except (KeyboardInterrupt, RuntimeError):
            loop.run_until_complete(my_board.shutdown())
            print('goodbye')
        finally:
            loop.close()
    
    import argparse
    import signal
    import sys
    import threading
    import time
    
    from python_banyan.banyan_base import BanyanBase
    
    
    class HCSR04(BanyanBase, threading.Thread):
        def __init__(self, **kwargs):
            """
            kwargs contains the following parameters
            :param back_plane_ip_address: If none, the local IP address is used
            :param process_name: HCSR04
            :param publisher_port: publishing port
            :param subscriber_port: subscriber port
            :param loop_time: receive loop idle time
            :param trigger_pin: GPIO trigger pin number
            :param echo_pin: GPIO echo pin number
            """
    
            self.back_plane_ip_address = kwargs['back_plane_ip_address'],
            self.process_name = kwargs['process_name']
            self.publisher_port = kwargs['publisher_port']
            self.subscriber_port = kwargs['subscriber_port'],
            self.loop_time = kwargs['loop_time']
            self.trigger_pin = kwargs['trigger_pin']
            self.echo_pin = kwargs['echo_pin']
            self.poll_interval = kwargs['poll_interval']
    
            self.last_distance_value = 0
    
            # initialize the base class
            super(HCSR04, self).__init__(back_plane_ip_address=kwargs['back_plane_ip_address'],
                                         subscriber_port=kwargs['subscriber_port'],
                                         publisher_port=kwargs['publisher_port'],
                                         process_name=kwargs['process_name'],
                                         loop_time=kwargs['loop_time'])
    
            threading.Thread.__init__(self)
            self.daemon = True
    
            self.lock = threading.Lock()
    
            # subscribe to receive messages from arduino gateway
            self.set_subscriber_topic('from_arduino_gateway')
    
            # enable hc-sr04 in arduino gateway
            payload = {'command': 'set_mode_sonar', 'trigger_pin': self.trigger_pin,
                       'echo_pin': self.echo_pin}
            self.publish_payload(payload, 'to_arduino_gateway')
    
            # start the thread
            self.start()
    
            try:
                self.receive_loop()
            except KeyboardInterrupt:
                self.clean_up()
                sys.exit(0)
    
        def incoming_message_processing(self, topic, payload):
            print(topic, payload)
            with self.lock:
                self.last_distance_value = payload['value']
    
        def run(self):
            while True:
                with self.lock:
                    distance = self.last_distance_value
                payload = {'distance': distance}
                topic = 'distance_poll'
                self.publish_payload(payload, topic)
                time.sleep(self.poll_interval)
    
    
    def hcsr04():
        parser = argparse.ArgumentParser()
        # allow user to bypass the IP address auto-discovery.
        # This is necessary if the component resides on a computer
        # other than the computing running the backplane.
        parser.add_argument("-b", dest="back_plane_ip_address", default="None",
                            help="None or IP address used by Back Plane")
        parser.add_argument("-i", dest="poll_interval", default=1.0,
                            help="Distance polling interval")
        parser.add_argument("-n", dest="process_name", default="HC-SRO4 Demo",
                            help="Set process name in banner")
        parser.add_argument("-p", dest="publisher_port", default="43124",
                            help="Publisher IP port")
        parser.add_argument("-s", dest="subscriber_port", default="43125",
                            help="Subscriber IP port")
        parser.add_argument("-t", dest="loop_time", default=".1",
                            help="Event Loop Timer in seconds")
        parser.add_argument("-x", dest="trigger_pin", default="12",
                            help="Trigger GPIO pin number")
        parser.add_argument("-y", dest="echo_pin", default="13",
                            help="Echo GPIO pin number")
    
        args = parser.parse_args()
    
        if args.back_plane_ip_address == 'None':
            args.back_plane_ip_address = None
        kw_options = {'back_plane_ip_address': args.back_plane_ip_address,
                      'publisher_port': args.publisher_port,
                      'subscriber_port': args.subscriber_port,
                      'process_name': args.process_name,
                      'loop_time': float(args.loop_time),
                      'trigger_pin': int(args.trigger_pin),
                      'echo_pin': int(args.echo_pin),
                      'poll_interval': int(args.poll_interval)
                      }
    
        # replace with the name of your class
        HCSR04(**kw_options)
    
    
    # signal handler function called when Control-C occurs
    def signal_handler(sig, frame):
        print('Exiting Through Signal Handler')
        raise KeyboardInterrupt
    
    
    # listen for SIGINT
    signal.signal(signal.SIGINT, signal_handler)
    signal.signal(signal.SIGTERM, signal_handler)
    
    if __name__ == '__main__':
        hcsr04()