バックグラウンド
相互に通信する必要がある 2 つの Python プロセスがあります。通信は、Pipe という名前のクラスによって処理されます。通信する必要がある情報のほとんどは辞書の形式で提供されるため、これ用に別のクラスを作成しました。そのため、Pipe はこれを行うための非常に単純なプロトコルを実装しています。
Pipe コンストラクタは次のとおりです。
def __init__(self,sPath):
"""
create the fifo. if it already exists just associate with it
"""
self.sPath = sPath
if not os.path.exists(sPath):
try:
os.mkfifo(sPath)
except:
raise Exception('cannot mkfifo at path \n {0}'.format(sPath))
self.iFH = os.open(sPath,os.O_RDWR | os.O_NONBLOCK)
self.iFHBlocking = os.open(sPath,os.O_RDWR)
したがって、理想的には、各プロセスで同じパスを使用してパイプを構築するだけで、うまく話すことができます。
ここではほとんど不要だと思うので、プロトコルについては省略します。
すべての読み取りおよび書き込み操作は、次の「基本」関数を使用します。
def base_read_blocking(self,iLen):
self.lock()
lBytes = os.read(self.iFHBlocking,iLen)
self.unlock()
return lBytes
def base_read(self,iLen):
print('entering base read')
self.lock()
lBytes = os.read(self.iFH,iLen)
self.unlock()
print('exiting base read')
return lBytes
def base_write_blocking(self,lBytes):
self.lock()
safe_write(self.iFHBlocking,lBytes)
self.unlock()
def base_write(self,lBytes):
print('entering base write')
self.lock()
safe_write(self.iFH,lBytes)
self.unlock()
print('exiting base write')
別の投稿で safe_write が提案されました
def safe_write(*args, **kwargs):
while True:
try:
return os.write(*args, **kwargs)
except OSError as e:
if e.errno == 35:
import time
print(".")
time.sleep(0.5)
else:
raise
ロックとロック解除は次のように処理されます。
def lock(self):
print('locking...')
while True:
try:
os.mkdir(self.get_lock_dir())
print('...locked')
return
except OSError as e:
if e.errno != 17:
raise e
def unlock(self):
try:
os.rmdir(self.get_lock_dir())
except OSError as e:
if e.errno != 2:
raise e
print('unlocked')
問題
これは時々起こります:
....in base_read
lBytes = os.read(self.iFH,iLen)
OSError: [Errno 11] Resource temporarily unavailable
時々それは大丈夫です。
魔法のソリューション
問題が発生するのを止めたようです。これは私自身の質問に答える私ではないことに注意してください。私の質問については、次のセクションで説明します。
読み取り関数を次のように変更すると、次のように整理されました。
def base_read(self,iLen):
while not self.ready_for_reading():
import time
print('.')
time.sleep(0.5)
lBytes = ''.encode('utf-8')
while len(lBytes)<iLen:
self.lock()
try:
lBytes += os.read(self.iFH,iLen)
except OSError as e:
if e.errno == 11:
import time
print('.')
time.sleep(0.5)
finally:
self.unlock()
return lBytes
def ready_for_reading(self):
lR,lW,lX = select.select([self.iFH,],[],[],self.iTimeout)
if not lR:
return False
lR,lW,lX = select.select([self.iFHBlocking],[],[],self.iTimeout)
if not lR:
return False
return True
質問
一時的に利用できない理由を正確に見つけるのに苦労しています。2 つのプロセスは、ロック メカニズムのために実際の名前付きパイプに同時にアクセスすることはできません (私が間違っていない限り?)。
私が本当に欲しいのは説明だけです...私が見つけた解決策は機能しますが、魔法のように見えます。誰でも説明できますか?
システム
- Ubuntu 12.04、
- Python3.2.3