如何在True的同时运行zmq和其他:同时独立运行?

时间:2017-12-03 12:38:17

标签: python python-2.7 zeromq python-multiprocessing pyzmq

我的服务器有这个代码:

import time
import zmq

context = zmq.Context()
socket = context.socket(zmq.REP)
socket.bind("tcp://*:5000")

while True:
    message = socket.recv()
    socket.send(b"World")
    print "sent"

while True:
    print "done."

我有一个单独的客户端脚本,每当我发送消息时,都会通过zmq向此消息发送消息。在服务器上(这个代码),如果我只有第一个True :,它打印"发送"每次我发送一条消息,如果我只有第二个,那么它会打印"完成。"不断。但是,如果我把它们都放在一起,它就永远不会完成打印(或者如果我切换它们的顺序并将它们都打印出来并且#34;发送"当我发送消息时#34;)。

作为输出,我希望它能够连续打印"完成。",并打印"发送"当我收到消息时所以像这样:

done.
done.
done.
done.
done.
sent
done.
lots more done....

基本上我希望两个循环连续且完全独立地运行。

N.B。我尝试过使用多处理(例如在这里的第3个答案How do I run two python loops concurrently?),但是也无法使用它。我尝试了如下:

import time
import zmq
from multiprocessing import Process

context = zmq.Context()
socket = context.socket(zmq.REP)
socket.bind("tcp://*:5000")
i = time.time()

def zmq_loop():
    while True:
        message = socket.recv()
        socket.send(b"World")
        print "sent"

def done_loop():
    global i
    while True:
        i2 = time.time()-i
        if i2%2 == 0:
            print "done."

if __name__ == "__main__":
    Process(target=zmq_loop).start()
    Process(target=done_loop).start()

1 个答案:

答案 0 :(得分:1)

正如昨天在this中解释的那样,[CONCURRENT]处理在技术上可以通过python中的几种不同方式实现,每种方式都有不同的成本。

今天,让我们看一下另一种方法 - 使用一个框架,它是用同样的动机开发的 - 拥有自然的 [CONCURRENT] - 调度 - 已经在DNA中 - 最初用于轻松编写和平滑操作复杂的GUI人机交互(MMI)。

这个框架可能并且将帮助您实现很多目标,因为事实上,它已经非常关注完全相同的情况,其中必须同时监控多个事物:

欢迎使用 Tkinter GUI框架,我们将仅将其用于智能并发操作的事件处理程序。

我曾多次感到惊讶,建立一个相当复杂的有限状态自动机(FSA)组合是多么容易,它可以顺利地合作(FSA-s联盟),使用独立,孤立的工具操作(每个FSA的内部逻辑),但能够轻松地将信号/消息从一个FSA传播到另一个FSA。是的,它们实际上可以在 1 -event-source-FSA :N -consumer(s)-FSA(s)中运行

您可以创建(使用 ZeroMQ始终以非阻塞方式)处理程序 - 一个“嗅探器”进行常规检查(最好通过超时控制) .poll() 方法{ NACK | POSACK }要阅读的任何内容) - 另一个“读者”,用于从ZeroMQ Socket()实例读取实际内容(触发)通过POSACK - 来自“嗅探器”的信号,如前所述 - 另一个“do-a-work-er”用于任何其他可能希望操作的任务

Tkinter .mainloop()方法是全局控制器,它为您编排脏工作。

Tkinter介导的代理协同处理的高级概念从main()开始,简单如下:

def main():
    root = Tk()                      # INIT a Tk() instance
    root.lift()                      #      + make it visible
    app = myApplication( root )      # SET ( [HERE] are all your app gems )
    root.mainloop()                  # START the core event-handling orchestrator

Tkinter可能看起来充满各种各样的GUI小工具,与你的问题无关,但不要惊慌。

Tkinter拥有令人难以置信的创建工具,可满足您的需求。

  • using control variables将用作存储,信号传递和传播价值变化的手段,在其他独立且明确不协调的参与者之间(参见“嗅探者”,“读者”,“工人”)和其他任何人......)

  • tools for handling events - real, abstract and even virtual

  • 用于处理定时操作的工具 - 以几乎轻量级的实时系统的形式,使用具有接下来将发生的优先时序的设置,.mainloop() - 任务要记住 明确指定的时间.after( thisAmountOfMILLISECONDS, callThisFUNCTION )或自由.after_idle( callAlwaysThatFUNCTION )

使用这些已经很完美的工具,人们不需要做任何事情来解决你的任务。

所以其余的原则在于你的创造力如何重新使用这些智能工具。

一个小型演示,如何让两个(​​3!)事件“同时独立”发生

让我们设置案例,当一个人想要同时处理(这里通过打印证明)几个独立的过程时。

    >>> #-----------------------------------------------FAST MOCK-UP EXAMPLE
    >>> import Tkinter as tk                          # python27
    >>> root = tk.Tk()
    >>> root.protocol( "WM_DELETE_WINDOW", root.quit() )
    '3071841620Ldestroy'
    >>> #------VAR-------------------------------------IMPORTANT TOOL:
    >>> aStringVAR = tk.StringVar()
    >>> aStringVAR.set( "_init_" )

    >>> def aKeyPressEventHANDLER( anEvent ): # SIMPLE EventHANDLER,
            #                                 #        also ignites remote responsive processes
    ...     aTemplate = "[KEY]::{3: >10s}\n<s/n>::{0: >10d}\n(=@=)::{1: > 10d}\n^from::({5:})"
    ...     sString   = aTemplate.format( anEvent.serial,
    ...                                   anEvent.time,
    ...                                   anEvent.char,
    ...                                   anEvent.keysym,
    ...                                   anEvent.keysym_num,
    ...                               str(anEvent.widget )
    ...                               )
    ...     aStringVAR.set( sString )
    ...     print sString
    ... 
    >>> #----VAR_TRACER----------------------------------------[#1]
    >>> def aVAR_TRACER_A( p1_quasiNAME, p2_indexOrEmptyString, p3_accessMODE ):
    ...     print "aVAR_TRACER_A()-called::(on){0:} traced_event({1:})".format( str( p1_quasiNAME ), str( p3_accessMODE ) )
    ...     # ###############=[A]#######
    ...     # < do some task =[A] here >
    ...     # ###############=[A]#######
    ...     print "aVAR_TRACER_A()         [{0:}]".format(   str( root.globalgetvar( p1_quasiNAME ) ).replace( " ", "" ) )
    ...

    >>> #----VAR_TRACER----------------------------------------[#2]
    >>> def aVAR_TRACER_B( p1_quasiNAME, p2_indexOrEmptyString, p3_accessMODE ):
    ...     print "aVAR_TRACER_B()-called::(on){0:} traced_event({1:})".format( str( p1_quasiNAME ), str( p3_accessMODE ) )
    ...     # ###############=[B]#######
    ...     # < do some task =[B] here >
    ...     # ###############=[B]######
    ...     print "aVAR_TRACER_B()         [{0:}]".format(   str( root.globalgetvar( p1_quasiNAME ) ).replace( " ", "" ) )
    ... 

    >>> #-----VAR_A_tracer_ID------------------------------"w" EVENT SNIFFER
    >>> aTraceVAR_A_tracer_ID = aStringVAR.trace_variable( "w", aVAR_TRACER_A )

    >>> #-----VAR_B_tracer_ID------------------------------"w" EVENT SNIFFER
    >>> aTraceVAR_B_tracer_ID = aStringVAR.trace_variable( "w", aVAR_TRACER_B )

    >>> #-----------tracer_ID values for ev. theirs resp. de-activation:
    >>> aTraceVAR_A_tracer_ID
    '3071960124LaVAR_TRACER_A'
    >>> aTraceVAR_B_tracer_ID
    '3071961284LaVAR_TRACER_B'

    >>> #---.bind()-----------------------EventHANDLER with a system event <KeyPress>
    >>> root.bind( "<KeyPress>", aKeyPressEventHANDLER ) # <-since here LIVE (!)
    '3071841740LaKeyPressEventHANDLER'
    >>> #------------------------------------------------^^^ since here, it went live
    >>> #                                                 1: having put a mouse on tk-window,
    >>> #                                                 2: set-focus by click
    >>> #                                                 3: started keys:
    >>> #                                                    ( "a",
    >>> #                                                       6-on-<NumKeyPad>,
    >>> #                                                       *-on-<NumKeyPad>

    >>> # this happened "independently, at the same time" ( see time (=@=):: values )
    >>> 

    aVAR_TRACER_B()-called::(on)PY_VAR0 traced_event(w)
    aVAR_TRACER_B()         [[KEY]::a<s/n>::832(=@=)::88486992^from::(.)]
    aVAR_TRACER_A()-called::(on)PY_VAR0 traced_event(w)
    aVAR_TRACER_A()         [[KEY]::a<s/n>::832(=@=)::88486992^from::(.)]
    [KEY]::         a
    <s/n>::       832
    (=@=)::  88486992
    ^from::(.)
    aVAR_TRACER_B()-called::(on)PY_VAR0 traced_event(w)
    aVAR_TRACER_B()         [[KEY]::KP_6<s/n>::832(=@=)::88509107^from::(.)]
    aVAR_TRACER_A()-called::(on)PY_VAR0 traced_event(w)
    aVAR_TRACER_A()         [[KEY]::KP_6<s/n>::832(=@=)::88509107^from::(.)]
    [KEY]::      KP_6
    <s/n>::       832
    (=@=)::  88509107
    ^from::(.)
    aVAR_TRACER_B()-called::(on)PY_VAR0 traced_event(w)
    aVAR_TRACER_B()         [[KEY]::KP_Multiply<s/n>::832(=@=)::88541180^from::(.)]
    aVAR_TRACER_A()-called::(on)PY_VAR0 traced_event(w)
    aVAR_TRACER_A()         [[KEY]::KP_Multiply<s/n>::832(=@=)::88541180^from::(.)]
    [KEY]::KP_Multiply
    <s/n>::       832
    (=@=)::  88541180
    ^from::(.)