I have this code for my server:
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."
I have a separate client script that sends a message through zmq to this one whenever i send a message. On the server (this code), if i only have the first while True:, it prints "sent" every time i send a message, and if i only have the second while True:, it prints "done." continuously. But if i put both, it never prints done (or if i switch their order and put both it never prints "sent" when i send a message").
As an output i want it to continuously print "done.", and also print "sent" when I get a message. So something like this:
done.
done.
done.
done.
done.
sent
done.
lots more done....
Basically i want both loops to run continuously and completely independently of each other.
N.B. I have tried using multiprocessing (such as in the 3rd answer here How do I run two python loops concurrently?), but couldn't get that to work either. I tried it as below:
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()
As was explained yesterday in this, the
[CONCURRENT]
-processing is technically achievable in several different ways in python, each with a way different cost.Today, let's have a look onto another approach - using a framework, that was developed with the very same motivation - having the natural
[CONCURRENT]
-scheduling-already-in-DNA - originally intended for easy composing and smooth operating complex GUI Man-Machine-Interactions ( MMI ).This framework may and will help you achieve a lot, right due to the fact, it has evolved with a lot of care for exactly the same scenarios, where more than one thing has to be monitored at once:
Welcome to
Tkinter
GUI framework, which we will use just for its smart concurrently operated event handlers.I was many times positively surprised, how easy it comes to build a quite complex composition of Finite-State-Automata ( FSA ), that smoothly cooperate together ( a coalition of FSA-s ), using tools for both independent, isolated operations ( the inner-logic of each FSA ), yet being easily able to propagate signals / messages from one FSA towards another(s). Yes, they can actually operate in 1-event-source-FSA : N-consumer(s)-FSA(s)
There you can create ( with ZeroMQ always in a non-blocking manner ) handlers -- one "sniffer" for a regular checking ( best by a timeout-controlled
.poll()
method to{ NACK | POSACK }
anything to read ) -- another "reader" for actual reading from the ZeroMQSocket()
instance ( triggered by thePOSACK
-signal from the "sniffer", as was mentioned previously -- another "do-a-work-er" for any other task one may wish to operateTkinter
.mainloop()
method is the global controller, which orchestrates the dirty job for you.The hich level concept of Tkinter-mediated agent's co-processing starts in
main()
as simple as:Tkinter might look as a garrage full of various GUI-gadgets, that have nothing to do with your problem, but don't panic.
Tkinter has incredibly well created tools right for your needs.
using control variables that will be used as a means for storing, signalling and propagating changes of values among otherwise independent and explicitly un-coordinated actors ( ref. "sniffer", "reader", "worker" and any others ... )
tools for handling events - real, abstract and even virtual
tools for handling timed-operations - in a form of an almost a lightweight real-time system, using setups with preferred timing of what shall happen next, the
.mainloop()
-yet tasked to bear in mindan explicitly specified timing
.after( thisAmountOfMILLISECONDS, callThisFUNCTION )
or a liberal.after_idle( callAlwaysThatFUNCTION )
.One does not need indeed anything more to go and solve your task, using these already perfect tools.
So all the rest is just in principle under your creativity how to re-use these smart tools.
A small demo,
how to make two ( 3 ! ) things happen "at the same time independently"
Let's setup the case, when one wants to process ( here demonstrated by a printing ) several independent processes, all at the same time.