Linux.Python.从命名管道中读取

Linux. Python. Read from named pipe

本文关键字:读取 管道 Python 从命 Linux      更新时间:2023-10-16

我在python中复制一些功能时遇到了问题。
在ubuntu下工作。
我有一个c++程序,它做一些事情,每隔一段时间它会把格式化的数据写入一个命名管道。我还有一个c++程序可以从命名管道中读取数据。没有问题。然而,我几乎不知道如何在python中复制相同的东西(只有读取部分)。

下面是我用来读取的c++代码:
//various includes
#define FIFO_NAME "/tmp/MYFIFO"
using namespace std;
int main()
{
    int fp;
    fp = open(FIFO_NAME, O_RDONLY);
    char readbuf[80];
    while (true)
    {
        int tot = 0;
        //read an int to know how many results are there to read right now
        while(tot<sizeof(int))
            tot+= read(fp, readbuf+tot, sizeof(int)-tot);
        int nres = *(int *)&readbuf[0];
        if (nres>0)
        {
            cout << nres << " results:" << endl;
            for (int i = 0; i < nres; i++)
            {
                //here I read 3 floats
            }
        }
    }
}

这段c++代码的工作方式完全符合我的要求:它从命名管道中读取字节,将它们转换为相应的数字,使它们可供我使用。
我试着用python做同样的事情,但是失败了。
第一次尝试python代码:

import os
import time
FIFO_NAME = '/tmp/MYFIFO'
def main():
    fp = os.open(FIFO_NAME, os.O_RDONLY)
    while True:
        time.sleep(0.001)
#Here I just try to read the first 4 bytes (the initial int) and fail already
        line = os.read(fp, 4) #I think this would read 4 bytes from the FIFO?
        print(len(line)) #ALWAYS prints 4
        print(line) #ALWAYS prints a blank line
        print(int(line)) #this of course gives an error, saying that line ==''

第二次尝试python代码(给出相同的错误结果):

import os
import time
FIFO_NAME = '/tmp/MYFIFO'
def main():
    fp = open(FIFO_NAME, 'r')
    while True:
        time.sleep(0.001)
#Here I try to read up to the line break
        line = fp.readline() #I think this would read to the line break, but it actually returns immediately
        print(len(line)) #after the first few iterations, this always prints 6
        print(line) #ALWAYS prints a blank line
在第二次尝试中,我希望读取到第一个换行符(我可以很容易地让c++生成器在每个"包"的末尾放一个换行符)。然而,这总是读取空行。

我的问题是关于在python中获得我在c++中拥有的功能。我可以通过两种方式看到:

  • 修复了我在python端使用管道的方式,通过实际读取字节,就像我在c++中做的那样,并将它们封送到正确的数据类型和值。
  • 让python"加载"一个字节缓冲区,直到它接收到换行符,然后从中提取我的数字。

无论如何,我不明白为什么read和readline返回那些空字符串,我也不知道如何处理它们。

我希望你们中的一些人能帮助我。请随时要求澄清和更多信息。

在我的评论中,我指的是python,但那是顺便说一下。
看看这个,它可能会对你有所帮助,因为它是专门关于"c#和Python之间的命名管道"的。
http://jonathonreinhart.blogspot.co.uk/2012/12/named-pipes-between-c-and-python.html

如果链接丢失了,下面是jonathon说的:

c#

// Open the named pipe.
var server = new NamedPipeServerStream("NPtest");
Console.WriteLine("Waiting for connection...");
server.WaitForConnection();
Console.WriteLine("Connected.");
var br = new BinaryReader(server);
var bw = new BinaryWriter(server);
while (true) {
    try {
        var len = (int) br.ReadUInt32();            // Read string length
        var str = new string(br.ReadChars(len));    // Read string
        Console.WriteLine("Read: "{0}"", str);
        str = new string(str.Reverse().ToArray());  // Just for fun
        var buf = Encoding.ASCII.GetBytes(str);     // Get ASCII byte array     
        bw.Write((uint) buf.Length);                // Write string length
        bw.Write(buf);                              // Write string
        Console.WriteLine("Wrote: "{0}"", str);
    }
    catch (EndOfStreamException) {
        break;                    // When client disconnects
    }
}
Console.WriteLine("Client disconnected.");
server.Close();
server.Dispose();
Python

import time
import struct
f = open(r'\.pipeNPtest', 'r+b', 0)
i = 1
while True:
    s = 'Message[{0}]'.format(i)
    i += 1
    f.write(struct.pack('I', len(s)) + s)   # Write str length and str
    f.seek(0)                               # EDIT: This is also necessary
    print 'Wrote:', s
    n = struct.unpack('I', f.read(4))[0]    # Read str length
    s = f.read(n)                           # Read str
    f.seek(0)                               # Important!!!
    print 'Read:', s
    time.sleep(2)

在这个例子中,我实现了一个非常简单的协议,其中每个"消息"是一个4字节的整数(c#中的UInt32, Python中的'I' (un)pack格式),它表示后面的字符串的长度。字符串为ASCII格式。这里需要注意的重要事项:

Pythonopen()的第三个参数表示"未缓冲的"。
否则,它将默认为行缓冲,这意味着在实际通过管道发送换行符之前,它将等待换行符。

我不知道为什么,但是省略seek(0)会导致IOError #0。
我是通过StackOverflow上的一个问题发现这一点的。