我有一个运行在Linux系统上的Python守护进程。 我想提供诸如“Bob”,“Alice”等的信息,并且具有守护进程打印“Hello Bob”。 和“你好爱丽丝”的文件。
这必须是asynchronous的。 Python守护进程必须等待信息,并在收到信息时进行打印。
什么是实现这个目标的最好方法?
我正在考虑命名pipe道或Queue
库,但可能有更好的解决scheme。
以下是你如何使用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。
有几个机制可以使用,但一切归结为使用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有一个内置的rpc库(使用xml进行数据编码)。 文档写得很好; 那里有一个完整的例子:
(python 2.7)或者
(python 3.3)
这可能值得考虑。
我不擅长python,所以我想分享一下
**通用进程间通信**
nc aka netcat是一个服务器客户端模型程序,允许通过网络发送文本,文件等数据。
nc
优点
例
在deamon
nc -l 1234 > output.txt
从其他程序或shell /终端/脚本
echo HELLO | nc 127.0.0.1 1234
nc可以通过使用系统命令调用函数(可以是os.system)来读取stdout。
为什么不使用信号?
我不是一个Python程序员,但可以在守护进程中注册一个信号处理程序,然后从终端发出信号。 只要使用SIGUSR或SIGHUP或类似的。
这是您用来旋转日志文件或类似的常用方法。
一个解决方案可能是使用简化服务器和客户端之间的通话的asynchat库 。
这里是一个你可以使用的例子(改编自这个网站 )
在deamon.py
,创建一个Chatserver
对象。 每次连接完成后, ChatHandler
创建一个ChatHandler
对象,并从asynchat.async_chat
继承。 该对象收集数据并将其填充到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)
大家都提到FIFO-s(在Linux术语中命名为管道)和XML-RPC,但是如果你现在正在学习这些东西,那么你也必须检查TCP / UDP / Unix套接字,因为它们是独立于平台的(至少TCP / UDP套接字是)。 如果你想要朝这个方向努力,你可以查看这个教程的一个工作示例或Python文档 。 由于大多数现代通信平台(XML-RPC,SOAP,REST)都使用这些基本的东西,所以它也很有用。