多个Python脚本向单个中央脚本发送消息

3 投票
3 回答
1164 浏览
提问于 2025-04-15 22:49

我有一些用Python 2.6写的脚本,可以随意运行。我想要一个中心脚本,能够收集这些脚本的输出,并把它们显示在一个统一的日志里。

理想情况下,这个中心脚本需要满足以下要求:

  • 每个脚本都能把消息发送到同一个“接收器”进行显示。
  • 如果接收器在第一个脚本尝试发送消息时没有运行,它会自动启动。
  • 接收器也可以手动启动和结束。(不过如果结束了,当另一个脚本尝试发送消息时,它会重新启动。)
  • 这些脚本可以按任何顺序运行,甚至可以同时运行。
  • 需要在Windows上运行。虽然如果能在多个平台上运行更好,但至少要能在Windows上工作。

我找到了一些线索:

根据这些信息,我觉得我可以拼凑出一些东西。只是想知道有没有明显的“正确”方法,或者我能否从别人的错误中学习。

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系统中对应的做法是什么。

撰写回答