Linux。 Python。从命名管道读取
Linux. Python. Read from named pipe
我在复制 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++ 制作人在每个 "packet" 的末尾放置一个换行符)。然而,这总是读取空行。
我的问题是关于 python 我在 C++ 中的功能。我可以通过两种方式看到这种情况:
- 修复我在 python 端使用管道的方式,就像我在 C++ 中所做的那样实际读取字节并将它们编组为正确的数据类型和值。
- 让 python "load" 有一个字节缓冲区,直到它收到换行符,然后从那里提取我的号码。
不管怎样,我不明白为什么 read 和 readline 返回那些空白字符串,我也不知道如何处理它们。
我希望你们中的一些人能帮助我。随时要求澄清和更多信息。
在我的评论中,我指的是 python,但顺便说一下。
看看这个,它可能会对你有所帮助,因为它专门针对 "Named Pipes between C# and Python".
http://jonathonreinhart.blogspot.co.uk/2012/12/named-pipes-between-c-and-python.html
万一 link 丢失,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'\.\pipe\NPtest', '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)
在这个例子中,我实现了一个非常简单的协议,其中每个 "message" 都是一个 4 字节整数(C# 中的 UInt32,Python 中的 'I' (un)pack 格式), 表示后面字符串的长度。字符串是 ASCII。此处需要注意的重要事项:
Python
open() 的第三个参数表示 "unbuffered".
否则,它将默认为行缓冲,这意味着它将在实际通过管道发送之前等待换行符。
我不确定为什么,但是省略 seek(0) 会导致 IOError #0。
Whosebug 的一个问题让我明白了这一点。
我在复制 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++ 制作人在每个 "packet" 的末尾放置一个换行符)。然而,这总是读取空行。
我的问题是关于 python 我在 C++ 中的功能。我可以通过两种方式看到这种情况:
- 修复我在 python 端使用管道的方式,就像我在 C++ 中所做的那样实际读取字节并将它们编组为正确的数据类型和值。
- 让 python "load" 有一个字节缓冲区,直到它收到换行符,然后从那里提取我的号码。
不管怎样,我不明白为什么 read 和 readline 返回那些空白字符串,我也不知道如何处理它们。
我希望你们中的一些人能帮助我。随时要求澄清和更多信息。
在我的评论中,我指的是 python,但顺便说一下。
看看这个,它可能会对你有所帮助,因为它专门针对 "Named Pipes between C# and Python".
http://jonathonreinhart.blogspot.co.uk/2012/12/named-pipes-between-c-and-python.html
万一 link 丢失,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'\.\pipe\NPtest', '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)
在这个例子中,我实现了一个非常简单的协议,其中每个 "message" 都是一个 4 字节整数(C# 中的 UInt32,Python 中的 'I' (un)pack 格式), 表示后面字符串的长度。字符串是 ASCII。此处需要注意的重要事项:
Python
open() 的第三个参数表示 "unbuffered".
否则,它将默认为行缓冲,这意味着它将在实际通过管道发送之前等待换行符。
我不确定为什么,但是省略 seek(0) 会导致 IOError #0。
Whosebug 的一个问题让我明白了这一点。