典型的な UNIX のやり方では、read(2)
ファイルの終わりを示すために 0 バイトを返します。これは次のことを意味します:
- ファイルにバイトがありません
- ソケットの反対側が接続をシャットダウンしました
- ライターがパイプを閉じました
あなたの場合、fifo.read()
ライターがファイル記述子を閉じているため、空の文字列が返されます。
そのケースを検出し、ループから抜け出す必要があります:
reader.py :
import os
import errno
FIFO = 'mypipe'
try:
os.mkfifo(FIFO)
except OSError as oe:
if oe.errno != errno.EEXIST:
raise
print("Opening FIFO...")
with open(FIFO) as fifo:
print("FIFO opened")
while True:
data = fifo.read()
if len(data) == 0:
print("Writer closed")
break
print('Read: "{0}"'.format(data))
セッション例
ターミナル 1 :
$ python reader.py
Opening FIFO...
<blocks>
ターミナル 2 :
$ echo -n 'hello' > mypipe
ターミナル 1 :
FIFO opened
Read: "hello"
Writer closed
$
アップデート 1 - 継続的に再開
おそらくライターが閉じられた後でも、パイプでの書き込みをリッスンし続けることを示しています。
これを効率的に行うために、次の事実を利用できます (そして利用すべきです)
<ブロック引用>通常、FIFO ブロックをもう一方の端も開くまで開きます。
ここで、open
の周りに別のループを追加します。 そして read
ループ。このように、パイプが閉じられると、コードはパイプを再度開こうとし、別のライターがパイプを開くまでブロックします:
import os
import errno
FIFO = 'mypipe'
try:
os.mkfifo(FIFO)
except OSError as oe:
if oe.errno != errno.EEXIST:
raise
while True:
print("Opening FIFO...")
with open(FIFO) as fifo:
print("FIFO opened")
while True:
data = fifo.read()
if len(data) == 0:
print("Writer closed")
break
print('Read: "{0}"'.format(data))
ターミナル 1 :
$ python reader.py
Opening FIFO...
<blocks>
ターミナル 2 :
$ echo -n 'hello' > mypipe
ターミナル 1 :
FIFO opened
Read: "hello"
Writer closed
Opening FIFO...
<blocks>
ターミナル 2 :
$ echo -n 'hello' > mypipe
ターミナル 1 :
FIFO opened
Read: "hello"
Writer closed
Opening FIFO...
<blocks>
...など。
man
を読むと、詳細を確認できます。 パイプのページ:
- PIPE(7) - Linux プログラマーズ マニュアル
- FIFO(7) - Linux プログラマーズ マニュアル
(数年後) for ... in ...
を使用してOPのユースケースを理解している場合 必要なことを正確に行います:
import os
FIFO = 'myfifo'
os.mkfifo(FIFO)
with open(FIFO) as fifo:
for line in fifo:
print(line)
このプログラムは、fifo からの入力が提供されるまで辛抱強く待ち、それを画面に出力します。その間、CPU は使用されません。
これは Python のより慣用的な方法でもあるため、直接 read() を使用するよりもお勧めします。
クライアント側の fifo への書き込みが終了すると、for ループが終了し、プログラムが終了します。次のクライアントが fifo を開くのを待つために fifo を再度開きたい場合は、 for
を置くことができます while ループへのセクション:
import os
FIFO = 'myfifo'
os.mkfifo(FIFO)
while True:
with open(FIFO) as fifo:
for line in fifo:
print(line)
これにより fifo が再開され、通常どおり待機します。