多个Python脚本向单个中央脚本发送消息
我有一些用Python 2.6写的脚本,可以随意运行。我想要一个中心脚本,能够收集这些脚本的输出,并把它们显示在一个统一的日志里。
理想情况下,这个中心脚本需要满足以下要求:
- 每个脚本都能把消息发送到同一个“接收器”进行显示。
- 如果接收器在第一个脚本尝试发送消息时没有运行,它会自动启动。
- 接收器也可以手动启动和结束。(不过如果结束了,当另一个脚本尝试发送消息时,它会重新启动。)
- 这些脚本可以按任何顺序运行,甚至可以同时运行。
- 需要在Windows上运行。虽然如果能在多个平台上运行更好,但至少要能在Windows上工作。
我找到了一些线索:
os.pipe()
multiprocess
- 占用一个端口
mutex
logging.handlers.SocketHandler
(感谢@Dan Head)
根据这些信息,我觉得我可以拼凑出一些东西。只是想知道有没有明显的“正确”方法,或者我能否从别人的错误中学习。
3 个回答
0
Dan Head的回答正是你需要的。
第二点,“如果接收方在第一个脚本尝试发送消息时没有运行,它会被启动”,这可能行不通。因为必须有东西在运行才能接收消息。我建议你写一个守护进程,这个进程在开机时启动,并告诉Windows如果它崩溃了就重启它。
1
我搭建了一个服务器,使用了Windows的命名管道,关键代码如下:
def run( self ):
# This is the main server loop for the Win32 platform
import win32pipe
import win32file
self.pipeHandle = win32pipe.CreateNamedPipe(
'\\\\.\\pipe\\myapp_requests',
win32pipe.PIPE_ACCESS_DUPLEX,
win32pipe.PIPE_TYPE_BYTE |
win32pipe.PIPE_READMODE_BYTE |
win32pipe.PIPE_WAIT,
1,
4096,
4096,
10000,
None)
if self.pipeHandle == win32file.INVALID_HANDLE_VALUE:
print 'Failed to create named pipe %s!' % self.pipeName
print 'Exiting...'
sys.exit(1)
while True:
# Open file connection
win32pipe.ConnectNamedPipe( self.pipeHandle )
# Run the main message loop until it exits, usually because
# of a loss of communication on the pipe
try:
self.messageLoop()
except ServerKillSignal:
break
# Return the pipes to their disconnected condition and try again
try: win32pipe.DisconnectNamedPipe( self.pipeHandle )
except: pass
win32file.CloseHandle( self.pipeHandle )
print "Exiting server"
这个方法messageLoop()
会从管道中读取数据,使用win32file.ReadFile()
,直到出现win32file.error的错误。这时它会退出,然后让run()
方法重新启动它。
在我的实现中,用户通常没有管理员权限,所以不能把它作为系统服务来启动。于是,我编写了客户端,让它检查管道是否存在,路径是'\.\pipe\pyccf_requests'。如果不存在,客户端就会启动一个新的服务器进程。
5
我建议你可以考虑使用logging.handlers.SocketHandler
来处理消息传递的部分,听起来你已经有了一个日志记录的使用场景。
标准库中的日志功能非常灵活,可以根据你的需求进行配置,所以你应该能够调整它们来满足你的要求。
不过,这个方法并没有解决你提到的自动重启的问题。对于UNIX系统,你可能会使用进程ID文件和os.kill(pid, 0)
来检查程序是否在运行,但我不太清楚在Windows系统中对应的做法是什么。