2012-11-12 23 views
7

TłoOSError: [Errno 11] Zasoby czasowo niedostępne. Co to powoduje?

Mam dwa procesy Pythona, które muszą komunikować się ze sobą. Kombinacja jest obsługiwana przez klasę o nazwie Pipe. Zrobiłem dla tego oddzielną klasę, ponieważ większość informacji, które muszą zostać przekazane, ma postać słowników, więc Pipe implementuje do tego prosty protokół.

Oto konstruktor rury:

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) 

Więc najlepiej byłoby po prostu zbudować rurę w każdym procesie z tej samej ścieżce i byliby w stanie mówić miłe.

Będę pomijać rzeczy o protokole, ponieważ myślę, że to w dużej mierze niepotrzebne tutaj.

Wszystkie operacje odczytu i zapisu skorzystać z następujących funkcji „bazy”:

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 został zaproponowany w innym poście

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 

blokowania i odblokowywania jest obsługiwany tak:

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') 

Problem

Ten czasami dzieje:

....in base_read 
lBytes = os.read(self.iFH,iLen) 
OSError: [Errno 11] Resource temporarily unavailable 

Czasami jest dobrze.

Magiczny Rozwiązanie

I wydaje się, że zatrzymał się problem z dzieje. Proszę zauważyć, że to nie ja odpowiadam na własne pytanie. Moje pytanie wyjaśniono w następnej sekcji.

zmieniłem odczytu funkcje wyglądają bardziej jak to i sortowane rzeczy się:

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 

Pytanie

Ja usiłuje dowiedzieć się dokładnie, dlaczego jest chwilowo niedostępny. Te dwa procesy nie mogą uzyskać dostępu do aktualnie nazwanej potoku w tym samym czasie z powodu mechanizmu blokującego (chyba że się mylę?), Tak jest z powodu czegoś bardziej fundamentalnego dla fifos, którego mój program nie bierze pod uwagę?

Wszystko, czego naprawdę chcę, to wyjaśnienie ... Rozwiązanie, które znalazłem działa, ale wygląda na magię. Czy ktoś może zaoferować wyjaśnienie?

systemu

  • Ubuntu 12.04,
  • Python3.2.3

Odpowiedz

3

Przedtem miałem similar problem with Java. Spójrz na zaakceptowaną odpowiedź - problemem było to, że tworzyłem nowe wątki w pętli. Proponuję zapoznać się z kodem tworzącym potok i upewnij się, że nie tworzysz wielu potoków.

+1

Chodzi o to, aby utworzyć wiele potoków. Tak więc proces A tworzy rurę, a proces B tworzy rurę o tej samej ścieżce. Następnie proces A może powiedzieć 'pipe.write (some_dictionary)', a proces B może powiedzieć 'some_dictionary = pipe.read()' – Sheena

+0

również, jeśli problem był liczbą uruchomionych rzeczy, wtedy wywołanie sleep() nie Naprawiać rzeczy. Chyba że czegoś brakuje ... – Sheena