我的服务器有这个代码:
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()
答案 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将用作存储,信号传递和传播价值变化的手段,在其他独立且明确不协调的参与者之间(参见“嗅探者”,“读者”,“工人”)和其他任何人......)
用于处理定时操作的工具 - 以几乎轻量级的实时系统的形式,使用具有接下来将发生的优先时序的设置,.mainloop()
- 任务要记住
明确指定的时间.after( thisAmountOfMILLISECONDS, callThisFUNCTION )
或自由.after_idle( callAlwaysThatFUNCTION )
。
使用这些已经很完美的工具,人们不需要做任何事情来解决你的任务。
所以其余的原则在于你的创造力如何重新使用这些智能工具。
让我们设置案例,当一个人想要同时处理(这里通过打印证明)几个独立的过程时。
>>> #-----------------------------------------------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::(.)