如何向Python守护进程提供信息



我有一个在Linux系统上运行的Python守护进程。我想提供诸如"Bob"、"Alice"等信息,并让守护进程将"Hello Bob"one_answers"Hello Alice"打印到一个文件中。

这必须是异步的。Python守护进程必须等待信息,并在收到信息时打印信息。

实现这一目标的最佳方式是什么?

我在考虑一个命名管道或Queue库,但可能有更好的解决方案。

以下是如何使用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()

你可以在shell会话中这样使用它

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

有几个选项

1) 如果守护程序应该接受来自其他系统的消息,则将守护程序设置为RPC服务器-使用xmlrpc/jsonrpc。

2) 如果它都是本地的,则可以使用TCP套接字或命名PIPE。

3) 如果将有大量客户端同时连接,则可以使用select.epoll.

python有一个内置的rpc库(使用xml进行数据编码)。文件写得很好;有一个完整的例子:

  • https://docs.python.org/2.7/library/xmlrpclib.html

(python 2.7)或

  • https://docs.python.org/3.3/library/xmlrpc.server.html#module-xmlrpc.server

(python 3.3)

这也许值得考虑。

每个人都提到了FIFO-s(在Linux术语中称为管道)和XML-RPC,但如果你现在学习这些东西,你也必须检查TCP/UDP/Unix套接字,因为它们是独立于平台的(至少TCP/UDP套接字是)。如果你想朝这个方向发展,你可以查看本教程中的工作示例或Python文档。它也很有用,因为大多数现代通信平台(XML-RPC、SOAP、REST)都使用这些基本的东西。

您可以使用一些机制,但一切都归结为使用IPC(进程间通信)。

现在,您将使用的实际机制取决于您可以实现的细节,不过一个好的解决方案是使用类似zmq的东西。

检查zmq 上pub/sub的以下示例

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

还有这个

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

对于非阻塞方式。

我不擅长python,所以我想与大家分享
**通用进程间通信**

nc又称netcat,是一个服务器-客户端模型程序,允许通过网络发送文本、文件等数据。

nc 的优点

  • 非常易于使用
  • IPC,甚至在不同编程语言之间
  • 内置于大多数linux操作系统

示例
关于deamon

nc -l 1234 > output.txt

来自其他程序或外壳/终端/脚本

echo HELLO | nc 127.0.0.1 1234

nc可以是python,通过使用系统命令调用函数(可能是os.system)并读取stdout。

为什么不使用信号?

我不是python程序员,但据推测,您可以在守护进程中注册一个信号处理程序,然后从终端发出信号。只需使用SIGUSR或SIGHUP或类似功能。

这是用于旋转日志文件或类似文件的常用方法。

一种解决方案可以是使用异步库来简化服务器和客户端之间的调用。

这里有一个你可以使用的例子(改编自本网站)

deamon.py中,创建了一个ChatServer对象。每次连接完成时,都会创建一个从asynchat.async_chat继承的ChatHandler对象。此对象收集数据并将其填充到self.buffer中。

当遇到特殊的字符串调用终止符时,数据应该是完整的,并调用方法found_terminator。正是在这种方法中,您可以编写自己的代码。

sender.py中,创建一个从asynchat.async_chat继承的ChatClient对象,在构造函数中设置连接,定义终止符(以防服务器应答!),并调用push方法发送数据。您必须将终止符字符串附加到数据中,以便服务器知道何时可以停止读取数据。

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)

最新更新