Linuxに名前付きパイプがあり、pythonから読みたいです。問題は、pythonプロセスが1つのコア(100%)を継続的に「消費」することです。私のコードは次のとおりです。
FIFO = '/var/run/mypipe'
os.mkfifo(FIFO)
with open(FIFO) as fifo:
while True:
line = fifo.read()
「スリープ」が状況またはプロセスがパイプからの入力データの一部を失うのを助けるかどうかを尋ねたいです。入力を制御できないため、データ入力の頻度がわかりません。選択と投票について読みましたが、問題の例が見つかりませんでした。最後に、100%の使用がデータ入力に影響を与えるかどうか(損失か何か?).
編集:ループを破りたくない。プロセスを継続的に実行し、パイプからのデータを「聞く」ようにします。
通常の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
$
おそらくライターが閉じた後でも、パイプ上の書き込みをリッスンし続けることを示します。
これを効率的に行うために、次の事実を利用できます(そして利用すべきです)。
通常、もう一方の端も開かれるまで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
ページを読むと、さらに学ぶことができます。
(後年)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を再度開き、次のクライアントが開くのを待つ場合は、for
セクションをwhileループに入れることができます。
import os
FIFO = 'myfifo'
os.mkfifo(FIFO)
while True:
with open(FIFO) as fifo:
for line in fifo:
print(line)
これにより、FIFOが再び開き、通常どおりに待機します。