mimipc
mimipc

Reputation: 1374

How to feed information to a Python daemon?

I have a Python daemon running on a Linux system. I would like to feed information such as "Bob", "Alice", etc. and have the daemon print "Hello Bob." and "Hello Alice" to a file.

This has to be asynchronous. The Python daemon has to wait for information and print it whenever it receives something.

What would be the best way to achieve this?

I was thinking about a named pipe or the Queue library but there could be better solutions.

Upvotes: 9

Views: 3336

Answers (8)

Gabor Garami
Gabor Garami

Reputation: 1267

Everyone mentioned FIFO-s (that's named pipes in Linux terminology) and XML-RPC, but if you learning these things right now, you have to check TCP/UDP/Unix sockets as well, since they are platform independent (at least, TCP/UDP sockets are). You can check this tutorial for a working example or the Python documentation if you want to go deper in this direction. It's also useful since most of the modern communication platforms (XML-RPC, SOAP, REST) uses these basic things.

Upvotes: 1

Guillaume Frichet
Guillaume Frichet

Reputation: 1

One solution could be to use the asynchat library which simplify calls between a server and a client.

Here is an example you could use (adapted from this site)

In deamon.py, a ChatServer object is created. Each time a connection is done, a ChatHandler object is created, inherited from asynchat.async_chat. This object collects data and fills it in self.buffer.

When a special string call the terminator is encountered, data is supposed to be complete and method found_terminator is called. It is in this method that you write your own code.

In sender.py, you create a ChatClient object, inherited from asynchat.async_chat, setup the connection in the constructor, define the terminator (in case the server answers !) and call the push method to send your data. You must append your terminator string to your data for the server to know when it can stop reading data.

daemon.py :

import asynchat
import asyncore
import socket

# Terminator string can be changed here
TERMINATOR = '\n'

class ChatHandler(asynchat.async_chat):
    def __init__(self, sock):
        asynchat.async_chat.__init__(self, sock=sock)

        self.set_terminator(TERMINATOR)
        self.buffer = []

    def collect_incoming_data(self, data):
        self.buffer.append(data)

    def found_terminator(self):
        msg = ''.join(self.buffer)

        # Change here what the daemon is supposed to do when a message is retrieved
        print 'Hello', msg

        self.buffer = []

class ChatServer(asyncore.dispatcher):
    def __init__(self, host, port):
        asyncore.dispatcher.__init__(self)
        self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
        self.bind((host, port))
        self.listen(5)

    def handle_accept(self):
        pair = self.accept()
        if pair is not None:
            sock, addr = pair
            print 'Incoming connection from %s' % repr(addr)
            handler = ChatHandler(sock)

server = ChatServer('localhost', 5050)

print 'Serving on localhost:5050'
asyncore.loop()

sender.py :

import asynchat
import asyncore
import socket
import threading

# Terminator string can be changed here
TERMINATOR = '\n'

class ChatClient(asynchat.async_chat):

    def __init__(self, host, port):
        asynchat.async_chat.__init__(self)
        self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
        self.connect((host, port))

        self.set_terminator(TERMINATOR)
        self.buffer = []

    def collect_incoming_data(self, data):
        pass

    def found_terminator(self):
        pass

client = ChatClient('localhost', 5050)

# Data sent from here
client.push("Bob" + TERMINATOR)
client.push("Alice" + TERMINATOR)

Upvotes: 0

There are several options

1) If the daemon should accept messages from other systems, make the daemon an RPC server - Use xmlrpc/jsonrpc.

2) If it is all local, you can use either TCP sockets or Named PIPEs.

3) If there will be a huge set of clients connecting concurrently, you can use select.epoll.

Upvotes: 5

Matt
Matt

Reputation: 213

Why not use signals?

I am not a python programmer but presumably you can register a signal handler within your daemon and then signal it from the terminal. Just use SIGUSR or SIGHUP or similar.

This is the usual method you use to rotate logfiles or similar.

Upvotes: 0

totti
totti

Reputation: 321

I'm not good in python so I would like to share
**Universal Inter process communcation **

nc a.k.a netcat is a server client model program which allow to send data such as text,files over network.

Advantages of nc

  • Very easy to use
  • IPC even between different programming langauges
  • Inbuilt on most linux OS

Example
On deamon

nc -l 1234 > output.txt

From other program or shell/terminal/script

echo HELLO | nc 127.0.0.1 1234

nc can be python by using the system command calling function ( may be os.system ) and read the stdout.

Upvotes: 0

hiro protagonist
hiro protagonist

Reputation: 46901

python has a built-in rpc library (using xml for data encoding). the documentation is well written; there is a complete example there:

(python 2.7) or

(python 3.3)

that may be worth considering.

Upvotes: 1

chthonicdaemon
chthonicdaemon

Reputation: 19810

Here is how you can do it with a fifo:

# receiver.py

import os
import sys
import atexit

# Set up the FIFO
thefifo = 'comms.fifo'
os.mkfifo(thefifo)

# Make sure to clean up after ourselves
def cleanup():
    os.remove(thefifo)
atexit.register(cleanup)

# Go into reading loop
while True:
    with open(thefifo, 'r') as fifo:
        for line in fifo:
            print "Hello", line.strip()

You can use it like this from a shell session

$ python receiver.py &
$ echo "Alice" >> comms.fifo
Hello Alice
$ echo "Bob" >> comms.fifo
Hello Bob

Upvotes: 11

Tasos Vogiatzoglou
Tasos Vogiatzoglou

Reputation: 2453

There are a few mechanisms you could use, but everything boils down to using IPC (inter-process communication).

Now, the actual mechanism you will use depends on the details of what you can achieve, a good solution though would be to use something like zmq.

Check the following example on pub/sub on zmq

http://learning-0mq-with-pyzmq.readthedocs.org/en/latest/pyzmq/patterns/pubsub.html

also this

http://learning-0mq-with-pyzmq.readthedocs.org/en/latest/pyzmq/multisocket/zmqpoller.html

for the non-blocking way.

Upvotes: 0

Related Questions