python - Linux 上 python 中的程序间通信

标签 python linux io

有很多关于如何做这些事情的例子:

1) 在同一个程序中的不同进程之间进行通信。

2) 通过网络在客户端/服务器之间进行通信

但是,这个问题在我看过的任何地方都没有很好的例子:

  • 从 python 程序 A 向程序 B 发送字符串的规范方法是什么,它会阻塞并处理该字符串,然后在循环中等待另一个字符串

我觉得我已经多次接近答案,但从未设法创建一个有效的示例。

其他隐含要求:

  • 实际上是两个不同的程序:该示例实际上需要有两个不同的程序(即两个文件 progA.py、progB.py,它们可以在同一台机器上的两个屏幕上分别从命令行运行),不使用任何类型的 fork 或多进程来创建客户端和服务器。
  • 请建议一种执行此操作的方法,该方法允许发送不超过合理长度的可变长度分隔字符串,而不必正确获取数据大小的确切字节数。 (后者在实现中更容易出错)。
  • 最好在不使用本地主机互联网连接的情况下执行此操作

例如;当读者使用时:

pipein = open(pipe_name, 'r')
while program.KeepRunning:
    action = pipein.readline()[:-1]
    program.processLine(line)
    time.sleep(1)

作者使用:

command = "enable"
pipeout = os.open(pipe_name, os.O_WRONLY)
os.write(pipeout, command)
os.write(pipeout, "\n")

http://www.python-course.eu/pipes.php 所建议 读者陷入无限循环,读出空字符串。

有趣的是,将 if(action == 'enable'): longFunction() 添加到 program.processLine 函数中会导致 中的部分代码longFunction 在卡住永远读出空行之前被执行。

另一方面,所有使用更现代的低级 subprocess 模块的示例仅涉及多线程应用程序,而不是多个应用程序。其他实现涉及套接字和网络。

虽然我已经尝试使用套接字,但这会导致一般的“出现错误”类型的错误,其中有许多可能的原因 错误 111:“连接被拒绝” 出现在“某些时候” .作为在收到某些命令时执行的 python 代码的一部分,实际上会修改网络配置(例如,它调用诸如 iptciptables 带有各种参数)利用到 localhost 的网络连接可能是应该避免的事情,这会导致难以调试和通常令人讨厌的问题。除了第二个程序在同一台机器上运行是不必要的部分之外,因此任何程序间通信都不需要使用网络接口(interface)。

最佳答案

这是预期的行为。看看this answer对于类似的问题和 FIFO 行为的概述。与您的问题相关的部分是:

When there are no more writers (...) readers are notified about that through read() returning the EOF.

file.readline() docs假设 ''(空字符串)意味着 EOF 已到达:

if f.readline() returns an empty string, the end of the file has been reached, while a blank line is represented by '\n', a string containing only a single newline.

就是这样。在每次尝试读取的无限循环中,您都会得到一个空字符串,表示没有更多的作者连接。

没有什么能阻止您使用命名管道来解决您的任务。最简单的方法就是在没有作家的时候睡一会儿。这是工作示例:

# server.py

import os
import time

pipe_name = 'pipe_test'

if not os.path.exists(pipe_name):
    os.mkfifo(pipe_name)

with open(pipe_name, 'r') as pipe:
    print("Listening for actions...")
    while True:
        action = pipe.readline()[:-1]
        if action == '':
            print("No clients. Sleeping...")
            time.sleep(1)
        else:
            print("Action received:", repr(action))
# client.py

import os

pipe_name = 'pipe_test'

if not os.path.exists(pipe_name):
    os.mkfifo(pipe_name)

print("Waiting for server to start...")
with open(pipe_name, 'w') as pipe:
    action = input("Enter action to send: ")
    pipe.write(action + '\n')

注意事项:

  • 使用 os.open() 没有意义,它是低级函数。您可以使用 open() 与命名管道进行交互。
  • 打开命名管道进行读取blocks直到第一个作家被连接。因此,在第一个客户端连接到管道之前,您不会在输出中看到 Listening for actions...。作家在没有读者的情况下开始也是如此。
  • 你问的是“哪个阻塞并处理这个字符串,然后在循环中等待另一个”。除非您在单独的线程中处理字符串,否则在处理当前字符串之前,它不会尝试读取下一个字符串。

关于python - Linux 上 python 中的程序间通信,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33231767/

相关文章:

linux - 通讯命令不比较单词

java - 在 InputStream 的 read() 中阻止 I/O

python - argparse.print_help() 不打印完整消息

python - 使用 Map-Reduce 时 Python 中的惰性 bool 求值

linux - 网络数据在同一物理主机上的两个 LXC 容器之间走什么路径?

python - 在 python 中将字节转换为 BufferedReader

.net - Haskell 或 F# 高吞吐量二进制 I/O

python - 为什么网络服务器提示西里尔字母,而命令行则不然?

python - 修改 Python 字典键

linux - 在 Makefile 中使用 xargs basename