没有STDOUT的两个python脚本之间的进程间通信

Posted

技术标签:

【中文标题】没有STDOUT的两个python脚本之间的进程间通信【英文标题】:Interprocess Communication between two python scripts without STDOUT 【发布时间】:2018-07-16 19:36:55 【问题描述】:

我正在尝试创建一个监控所有线程的 Monitor 脚本或一个运行多个记录器、多个线程的大型 python 脚本。

我可以从 Monitor.py 运行子进程并转发可能包含我的线程状态的 STDOUT。但由于有几个记录器正在运行,我看到其他记录在其中..

问题:如何将主脚本作为一个单独的进程运行并获取自定义消息、线程状态而不干扰日志记录。 (将 PIPE 作为参数传递?)

Main_Script.py * 运行多个线程 * 每个线程都有单独的 Logger。

Monitor.py * 启动 Main_script.py * 监控 MainScript.py 中的每个线程(将来可能会从 Main_script 获取其他消息)

到目前为止,我尝试了子进程,来自 Multiprocessing 的进程。

子进程让我启动 Main_script 并将标准输出转发回监视器,但我看到通过同一个标准输出进入的线程日志记录。我正在使用“import logging”库将每个线程的数据记录到单独的文件中。

我尝试了 Multiprocessing 中的“process”。我不得不将 main_script.py 的主函数作为一个进程调用,并从 monitor.py 向它发送一个 PIPE 参数。现在,当我运行 top 命令时,我无法将 Main_script.py 视为一个单独的进程。

【问题讨论】:

问题:所有记录器都需要访问所有行还是负载平衡? 我认为记录器是根据关键字进行记录的……然后将它们拉入单独的文件中…… 【参考方案1】:

通常,您希望将子进程更改为像典型的 Unix 用户空间工具一样工作:日志记录和其他边带信息进入标准错误(或文件,或系统日志等),只有实际输出转到标准输出。

那么,问题很简单:只需将stdout 捕获到您处理的PIPE,然后将stderr 捕获到另一个PIPE,或者将其传递给真正的stderr


如果由于某种原因这不合适,您需要为 IPC 提供一些其他机制:Unix 或 Windows 命名管道,通过在 fork/exec 上泄漏文件描述符而传递的匿名管道,然后将 fd 作为参数传递、Unix 域套接字、TCP 或 UDP localhost 套接字、更高级别的协议(如 TCP 套接字之上的 Web 服务)、mmapped 文件、匿名 mmaps 或您之间传递的管道通过 Unix 域套接字或 Windows API 调用处理,...

如您所见,有很多选择。除了您想要“自定义消息”之外,如果对您的问题一无所知,就不可能告诉您您想要哪一个。

虽然我们正在这样做:如果您可以围绕multiprocessing 而不是subprocess 重写您的代码,那么该模块中内置了很好的高级抽象。例如,您可以使用Queue 自动管理同步和阻塞,还可以管理酸洗/解酸,因此您可以只传递任何(可酸洗的)对象,而不必担心序列化为文本和解析文本。或者,您可以创建共享内存来保存 int32 对象数组、NumPy 数组或您使用ctypes 定义的任意结构。等等。当然,您可以自己构建相同的抽象,而无需使用 multiprocessing,但是当它们开箱即用时会容易得多。


最后,虽然您的问题被标记为 ipcpipe,并且标题为“进程间通信”,但您的描述是指线程,而不是进程。如果你真的在一个进程中使用了一堆线程,你就不需要这些了。

您可以将结果粘贴在 queue.Queue 上,或者将它们存储在 listdeque 中,并在其周围加上 Lock,或者传入一个回调以在每个新结果中调用,或者使用像concurrent.futures.ThreadPoolExecutor这样的高级抽象,并返回Future对象或Futures的迭代器等。

【讨论】:

以上是关于没有STDOUT的两个python脚本之间的进程间通信的主要内容,如果未能解决你的问题,请参考以下文章

使用修改后的 python 解释器进行进程间通信

将 stdout 和 stderr 管道传输到 shell 脚本中的两个不同进程?

Python:在记录内存时获取子进程 STDOUT

如何在 Python 中进行跨进程跨脚本同步

Python3.5子进程错误

Python 3 TypeError: must be str, not bytes with sys.stdout.write()