したがって、相互に通信する必要がある 2 つの Python3.2 プロセスがあります。伝達する必要がある情報のほとんどは、標準的な辞書です。名前付きパイプを使用する方法が適しているように思われたので、両方のプロセスでインスタンス化できるパイプ クラスを作成しました。このクラスは、情報を取得するための非常に基本的なプロトコルを実装しています。
私の問題は、機能する場合と機能しない場合があることです。コードが失敗する場所を除いて、この動作にはパターンがないようです。
Pipe クラスの重要な部分は次のとおりです。さらにコードが必要な場合は叫んでください:
class Pipe:
"""
there are a bunch of constants set up here. I dont think it would be useful to include them. Just think like this: Pipe.WHATEVER = 'WHATEVER'
"""
def __init__(self,sPath):
"""
create the fifo. if it already exists just associate with it
"""
self.sPath = sPath
if not os.path.exists(sPath):
os.mkfifo(sPath)
self.iFH = os.open(sPath,os.O_RDWR | os.O_NONBLOCK)
self.iFHBlocking = os.open(sPath,os.O_RDWR)
def write(self,dMessage):
"""
write the dict to the fifo
if dMessage is not a dictionary then there will be an exception here. There never is
"""
self.writeln(Pipe.MESSAGE_START)
for k in dMessage:
self.writeln(Pipe.KEY)
self.writeln(k)
self.writeln(Pipe.VALUE)
self.writeln(dMessage[k])
self.writeln(Pipe.MESSAGE_END)
def writeln(self,s):
os.write(self.iFH,bytes('{0} : {1}\n'.format(Pipe.LINE_START,len(s)+1),'utf-8'))
os.write(self.iFH,bytes('{0}\n'.format(s), 'utf-8'))
os.write(self.iFH,bytes(Pipe.LINE_END+'\n','utf-8'))
def readln(self):
"""
look for LINE_START, get line size
read until LINE_END
clean up
return string
"""
iLineStartBaseLength = len(self.LINE_START)+3 #'{0} : '
try:
s = os.read(self.iFH,iLineStartBaseLength).decode('utf-8')
except:
return Pipe.READLINE_FAIL
if Pipe.LINE_START in s:
#get the length of the line
sLineLen = ''
while True:
try:
sCurrent = os.read(self.iFH,1).decode('utf-8')
except:
return Pipe.READLINE_FAIL
if sCurrent == '\n':
break
sLineLen += sCurrent
try:
iLineLen = int(sLineLen.strip(string.punctuation+string.whitespace))
except:
raise Exception('Not a valid line length: "{0}"'.format(sLineLen))
#read the line
sLine = os.read(self.iFHBlocking,iLineLen).decode('utf-8')
#read the line terminator
sTerm = os.read(self.iFH,len(Pipe.LINE_END+'\n')).decode('utf-8')
if sTerm == Pipe.LINE_END+'\n':
return sLine
return Pipe.READLINE_FAIL
else:
return Pipe.READLINE_FAIL
def read(self):
"""
read from the fifo, make a dict
"""
dRet = {}
sKey = ''
sValue = ''
sCurrent = None
def value_flush():
nonlocal dRet, sKey, sValue, sCurrent
if sKey:
dRet[sKey.strip()] = sValue.strip()
sKey = ''
sValue = ''
sCurrent = ''
if self.message_start():
while True:
sLine = self.readln()
if Pipe.MESSAGE_END in sLine:
value_flush()
return dRet
elif Pipe.KEY in sLine:
value_flush()
sCurrent = Pipe.KEY
elif Pipe.VALUE in sLine:
sCurrent = Pipe.VALUE
else:
if sCurrent == Pipe.VALUE:
sValue += sLine
elif sCurrent == Pipe.KEY:
sKey += sLine
else:
return Pipe.NO_MESSAGE
ここで失敗することがあります(readlnで):
try:
iLineLen = int(sLineLen.strip(string.punctuation+string.whitespace))
except:
raise Exception('Not a valid line length: "{0}"'.format(sLineLen))
他の場所では失敗しません。
エラーの例は次のとおりです。
Not a valid line length: "KE 17"
断続的であるという事実は、ある種の競合状態が原因であると私に言っています。私はそれが何であるかを理解するのに苦労しています. 何か案は?
プロセスの呼び出しに関する追加の編集
パイプの使用方法は、同じパスでコンストラクターを呼び出すことにより、processA と ProcessB でインスタンス化されます。次に、プロセス A がパイプに断続的に書き込み、プロセス B がそこから読み取ろうとします。物事を双方向として機能させようとすることは決してありません。
これは、状況のより長い説明です。私は質問を短くしようとしてきましたが、それをあきらめる時が来たと思います。とにかく、いい感じにプレイする必要があるデーモンと Pyramid プロセスがあります。使用中の Pipe インスタンスは 2 つあります。1 つは Pyramid のみが書き込み、もう 1 つはデーモンのみが書き込みます。Pyramid が書いたものは本当に短いです。私はこのパイプでエラーを経験したことがありません。デーモンが書くものはずっと長く、これは私に悲しみを与えているパイプです. どちらのパイプも同じ方法で実装されます。どちらのプロセスも、それぞれのパイプに辞書を書き込むだけです (そうでない場合は、Pipe.write に例外が発生します)。
基本的なアルゴリズムは次のとおりです: Pyramid はデーモンを生成し、デーモンは運命のクレイズ オブジェクト階層と膨大な RAM 消費をロードします。Pyramid は POST リクエストをデーモンに送信し、デーモンは大量の計算を行い、データを Pyramid に送信して、人間に優しいページをレンダリングできるようにします。その後、人間は HTML フォームなどに入力することで階層内にあるものに応答できるため、ピラミッドは別の辞書をデーモンに送信し、デーモンは辞書の応答を返します。
つまり、1 つのパイプだけが問題を示しており、問題のあるパイプには他のパイプよりも多くのトラフィックがあり、辞書のみがいずれかに書き込まれることが保証されています。
質問とコメントへの応答として編集
試してみるように言う前に... 読み物を除いて。例外がまったく発生するという事実は、私を悩ませているものです。iLineLengh = int(stuff) は、常に整数のように見える文字列を渡す必要があるように見えます。これはほとんどの場合であり、すべてではありません。したがって、おそらく整数ではないことについてコメントしたいという衝動を感じた場合は、コメントしないでください。
私の質問を言い換えると、競合状態を見つければ、あなたは私のヒーローになります。
少し例を編集します。
process_1.py:
oP = Pipe(some_path)
while 1:
oP.write({'a':'foo','b':'bar','c':'erm...','d':'plop!','e':'etc'})
プロセス_2.py:
oP = Pipe(same_path_as_before)
while 1:
print(oP.read())