Sending log entries to a logging mailslot which may or may not be running without needing to know which server is hosting it.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | import threading
from winsys import ipc
def logger ():
with ipc.mailslot ("logger") as l:
while True:
word = l.get ()
if word == "STOP":
break
else:
print word
threading.Thread (target=logger).start ()
with ipc.mailslot (r"\\*\mailslot\logger") as logging_mailslot:
for word in "the quick brown fox".split ():
logging_mailslot.put (word)
logging_mailslot.put ("STOP")
|
This is where mailslots really score over named pipes, sockets, etc. You can send messages to a named mailslot without knowing where it is or if it’s even running. Furthermore, there may be several active mailslots with the same name, all of which will receive the data sent.
The obvious application is for centralised or distributed logging but it could also be used as a form of pub-sub mechanism, at least for small pieces of data. The maximum message size across the network is about 400 bytes.
The mailslot() function is the quickest way to get hold of a mailslot for reading or writing. It provides useful defaults especially for local mailslots where the full path can be determined. Since the underlying Mailslot can be context-managed, I’ve enclosed the activity of each mailslot in a “with” block.
For simplicity I’ve run a reading mailslot inside a thread. For a clearer demonstration you could run the same code in a separate process, ideally on a separate machine within the same domain.
Read and write to local named mailslot, interleaving reads and writes.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | import random
from winsys import ipc
reader = ipc.mailslot ("reader")
writer = ipc.mailslot ("reader")
message = list (reversed ("the quick brown fox jumps over the lazy dog".split ()))
while True:
try:
data = reader.get (block=False, timeout_ms=1000)
if data == "STOP":
break
except ipc.x_mailslot_empty:
pass
else:
print data
if random.randint (1, 100) > 95:
try:
writer.put (message.pop ())
except IndexError:
writer.put ("STOP")
|
Although the most likely application of mailslots is from separate threads or processes on separate machines even, it’s quite possible for the same thread to read from and write to the same mailslot. The caveat is that one object must be obtained for reading and another for writing. They are linked by passing the same name to mailslot().
We make use of the fact that the Mailslot objects are mimicking Python’s Queue objects. This includes a Mailslot.get() method which has a timeout option. Using this, we can check for active messages and pass on by if none is present. We then randomly put one word from our message into the mailslot from the writer’s end and go round again. Finally, we send our STOP sentinel so that both ends release their respective mailslot handles.
Iterate over the contents of a mailslot