GNU/Linux >> Linux の 問題 >  >> Linux

PIPE という名前の Python 読み取り

典型的な 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 が再開され、通常どおり待機します。


Linux
  1. Linuxでパイプと名前付きパイプを使用する方法(例付き)

  2. ModuleNotFoundError:「IPython」という名前のモジュールがありません[修正]

  3. Ifsを理解していますか?

  1. 名前付きパイプ(猫または尾-f)からの連続読み取り?

  2. Linux Bash での名前付きパイプの使用例

  3. poll() を使用した名前付きパイプの O_RDWR

  1. Preugコマンド– SyntaxError:「print」の呼び出しに括弧がありません–解決策

  2. Fifoと一時ファイルまたはパイプを使用する目的は?

  3. この bash パイプ構造を使用するとデータが失われるように見えるのはなぜですか?