Python进程间查询/控制

6

我有一个基于Python的服务守护进程,正在执行大量的多路复用IO(select)。

从另一个脚本(也是Python)中,我想查询此服务进程的状态/信息和/或控制处理(例如,暂停它,关闭它,更改一些参数等)。

使用Python发送控制消息(“从现在开始你这样处理!”)和查询已处理数据(“那个的结果是什么?”)的最佳方法是什么?

我曾经在某处看到过命名管道可能有效,但不太了解命名管道,特别是在Python中 - 是否还有更好的选择。

后台服务守护进程和前端都将由我编写,因此所有选项都可行 :)

我正在使用Linux。

2个回答

9
管道和命名管道是不同进程之间通信的好方法。 管道的工作方式类似于共享内存缓冲区,但在两端都有类似简单文件的接口。一个进程在管道的一端写入数据,另一个进程在另一端读取该数据。 命名管道与上述相似,除了此管道实际上与计算机中的真实文件相关联。 更多详情请参考以下链接: 在Python中,使用os.mkfifo调用可以创建命名管道文件。
x = os.mkfifo(filename)

在子进程和父进程中,将此管道作为文件打开。
out = os.open(filename, os.O_WRONLY)
in = open(filename, 'r')

写作

os.write(out, 'xxxx')

阅读

lines = in.readline( )

编辑:添加自stackoverflow链接

您可能需要了解更多关于“IPC和Python”的信息


谢谢,伙计。这是我描述的任务的首选方式吗? - agnsaft
1
@invictus:你可以通过这种方式发送很多自定义消息,进程可以处理。但是对于关闭等操作,最好在进程中使用信号和信号处理程序。 - pyfunc
如果我需要多个前端同时与服务进行通信,那么为了正确地“定位”查询结果,我还需要多个命名管道吗? - agnsaft
1
@invictus:是的,它支持双向读写。设置取决于您想要实现什么。如果您有多个前端与服务通信,我建议使用基于套接字的解决方案,其中服务器可以侦听、连接和响应命令消息。 - pyfunc

3

使用消息队列是在Python中进行IPC的最佳方式,如下所示:

服务器进程 server.py (在运行 client.py 和 interact.py 之前,请先运行此文件)

from multiprocessing.managers import BaseManager
import Queue
queue1 = Queue.Queue()
queue2 = Queue.Queue()
class QueueManager(BaseManager): pass
QueueManager.register('get_queue1', callable=lambda:queue1)
QueueManager.register('get_queue2', callable=lambda:queue2)
m = QueueManager(address=('', 50000), authkey='abracadabra')
s = m.get_server()
s.serve_forever()

用于输入输出的交互actor,文件名为interact.py。

from multiprocessing.managers import BaseManager
import threading
import sys
class QueueManager(BaseManager): pass
QueueManager.register('get_queue1')
QueueManager.register('get_queue2')
m = QueueManager(address=('localhost', 50000),authkey='abracadabra')
m.connect()
queue1 = m.get_queue1()
queue2 = m.get_queue2()

def read():
    while True:
        sys.stdout.write(queue2.get())

def write():
    while True:
        queue1.put(sys.stdin.readline())
threads = []

threadr = threading.Thread(target=read)
threadr.start()
threads.append(threadr)

threadw = threading.Thread(target=write)
threadw.start()
threads.append(threadw)

for thread in threads:
    thread.join()

客户端程序Client.py。
from multiprocessing.managers import BaseManager
import sys
import string
import os

class QueueManager(BaseManager): pass
QueueManager.register('get_queue1')
QueueManager.register('get_queue2')
m = QueueManager(address=('localhost', 50000), authkey='abracadabra')
m.connect()
queue1 = m.get_queue1()
queue2 = m.get_queue2()


class RedirectOutput:
    def __init__(self, stdout):
        self.stdout = stdout
    def write(self, s):
        queue2.put(s)

class RedirectInput:
    def __init__(self, stdin):
        self.stdin = stdin
    def readline(self):
        return queue1.get()

# redirect standard output

sys.stdout = RedirectOutput(sys.stdout)

sys.stdin = RedirectInput(sys.stdin)

# The test program which will take input and produce output 
Text=raw_input("Enter Text:")
print "you have entered:",Text
def x():
    while True:
        x= raw_input("Enter 'exit' to end and some thing else to continue")
        print x
        if 'exit' in x:
            break
x()

这可以用于在网络或同一台机器上的两个进程之间进行通信。请记住,直到您手动杀死它为止,inter-actor和server进程将不会终止。


1
这看起来很有用(不知道今天你是否仍然会使用Python 3来设置它),但是明确一下,据我理解,服务器进程仅存在于定义队列的目的,互动器进程是执行后台工作的服务进程,而客户端则提供对互动器的用户交互控制,是这样吗? - Mike Lippert

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接