Python UNIX命名管道文件的结尾

Python UNIX命名管道文件的结尾,python,linux,loops,pipe,eof,Python,Linux,Loops,Pipe,Eof,我正在尝试使用一个名为pipe的unix来输出正在运行的服务的统计信息。我打算提供一个类似于/proc的界面,在这里可以通过catting文件查看实时统计数据 我在python代码中使用了类似的代码: while True: f = open('/tmp/readstatshere', 'w') f.write('some interesting stats\n') f.close() /tmp/readstathere是由mknod创建的命名管道 然后,我对其进行cat以查看统计

我正在尝试使用一个名为pipe的unix来输出正在运行的服务的统计信息。我打算提供一个类似于
/proc
的界面,在这里可以通过catting文件查看实时统计数据

我在python代码中使用了类似的代码:

while True:
  f = open('/tmp/readstatshere', 'w')
  f.write('some interesting stats\n')
  f.close()
/tmp/readstathere
是由
mknod
创建的命名管道

然后,我对其进行cat以查看统计信息:

$ cat /tmp/readstatshere
some interesting stats
它大部分时间都很好用。但是,如果我快速连续多次对条目进行cat,有时会得到多行
一些有趣的统计数据,而不是一行。有一两次,它甚至进入了一个无限循环,永远打印这一行,直到我杀死它。到目前为止,我得到的唯一修复方法是在
f.close()
之后设置500毫秒的延迟,以防止出现此问题

我想知道为什么会发生这种情况,以及是否有更好的方法来处理它


提前感谢

在这里,管道是错误的解决方案。如果要呈现流程内部状态的一致快照,请将其写入临时文件,然后将其重命名为“public”名称。这将防止在更新状态时,其他进程读取状态时可能出现的所有问题。另外,不要在繁忙循环中这样做,最好是在更新之间至少休眠一秒钟的线程中这样做。

不要写入实际文件。这不是
/proc
所做的。Procfs提供了一个虚拟(非磁盘备份)文件系统,可根据需要生成所需信息。您也可以做同样的事情,但是如果它不绑定到文件系统,那么就更容易了。相反,只需在Python程序中运行一个web服务,并将统计数据保存在内存中。当收到统计数据的请求时,将它们组织成一个漂亮的字符串并返回。大多数情况下,您不需要浪费时间更新在下次更新之前可能无法读取的文件。

在发出
关闭
后,您需要
取消管道的链接。我认为这是因为存在一种竞争条件,即管道可以在
cat
完成之前再次打开读取,因此它可以看到更多数据并将其读出,从而导致“一些有趣的统计数据”的倍数

基本上你想要的是:

while True:
    os.mkfifo(the_pipe)
    f = open(the_pipe, 'w')
    f.write('some interesting stats')
    f.close()
    os.unlink(the_pipe)
更新1:调用
mkfifo


更新2:如注释中所述,此代码中存在争用条件以及多个使用者。

UNIX套接字而不是管道怎么样

在这种情况下,您可以通过及时提供新数据对每个连接作出反应

唯一的缺点是您不能
cat
数据;您必须创建一个新的套接字句柄,并将
connect()
连接到套接字文件

MYSOCKETFILE = '/tmp/mysocket'
import socket
import os
try:
    os.unlink(MYSOCKETFILE)
except OSError: pass
s = socket.socket(socket.AF_UNIX)
s.bind(MYSOCKETFILE)
s.listen(10)
while True:
    s2, peeraddr = s.accept()
    s2.send('These are my actual data')
    s2.close()
查询此套接字的程序:

MYSOCKETFILE = '/tmp/mysocket'
import socket
import os
s = socket.socket(socket.AF_UNIX)
s.connect(MYSOCKETFILE)
while True:
    d = s.recv(100)
    if not d: break
    print d
s.close()

我想你应该用保险丝。 它具有python绑定,请参见
这使您可以编写对posix文件系统调用问题的答案

是否有理由使用命名管道与常规文件?@Mansour Merge complete。由于linux缓冲区缓存存在死锁问题,我实际上无法在缓存上创建脏页。这就是我选择管道的原因。嗯,根据我到目前为止的理解和测试,python代码在
open
上阻塞,直到另一个进程打开管道进行读取-通过这种行为,它看起来像
/proc
。问题是,
open
有时不阻塞,这会导致输出多个统计数据。创建一个普通的TCP套接字是我的第一选择,但这意味着需要另一个小程序来读取统计数据。我只是想让事情简单化和最小化。@Mansour并没有在实际文件中写入内容。他正在使用一个命名的管道<代码>写入
调用将被阻止,直到读卡器准备就绪-不会浪费任何周期。取消链接不会完全删除管道吗?谁会再次创造它?哇,说得好。在我的示例中,错过了对
mkfifo
的调用。我会更新它。好的,但是如果读卡器试图打开管道,在
os.unlink
os.mkfifo
之间会有一个竞争条件。你说得对。我在实践中没有看到过这种特殊的竞争,但我只在一个消费者(无论是
cat
还是另一个Python脚本)中尝试过。是的,我首先考虑了这一点,但我试图避免编写一个单独的程序来与套接字(在我的例子中是TCP)进行对话。这种解决方案似乎有些过头了。