2012-01-16 14 views
5

Próbuję uruchomić trzy funkcje (każda może wykonać do 1 sekundy, aby wykonać) co sekundę. Chciałbym wtedy przechowywać dane wyjściowe z każdej funkcji i zapisać je w osobnych plikach.Uruchamiaj wiele funkcji co sekundę, zapisuj wyniki do pliku

W tej chwili używam Timer do obsługi opóźnienia. (Mogę podklasy Thread, ale to już trochę skomplikowane dla tego prostego skryptu)

def main: 
    for i in range(3): 
     set_up_function(i) 
     t = Timer(1, run_function, [i]) 
     t.start() 
    time.sleep(100) # Without this, main thread exits 

def run_function(i): 
    t = Timer(1, run_function, [i]) 
    t.start() 
    print function_with_delay(i) 

Jaki jest najlepszy sposób obsłużyć wyjście z function_with_delay? Dołącz wynik do globalnej listy dla każdej funkcji?

Wtedy mógłbym umieścić coś takiego na koniec mojego Główną funkcją:

... 
while True: 
    time.sleep(30) # or in a try/except with a loop of 1 second sleeps so I can interrupt 
    for i in range(3): 
     save_to_disk(data[i]) 

Myśli?


Edycja: Dodano własną odpowiedź jako możliwość

Odpowiedz

7

Wierzę, że moduł python Queue jest przeznaczony do tego rodzaju scenariusza. Można zrobić coś takiego, na przykład:

def main(): 
    q = Queue.Queue() 
    for i in range(3): 
     t = threading.Timer(1, run_function, [q, i]) 
     t.start() 

    while True: 
     item = q.get() 
     save_to_disk(item) 
     q.task_done() 

def run_function(q, i): 
    t = threading.Timer(1, run_function, [q, i]) 
    t.start() 
    q.put(function_with_delay(i)) 
+1

+1 Działa to, ponieważ wyjście służy do oddzielania plików. Jeśli nie było to trywialne i wiązało się z kombinacją wyników, to przed rozpoczęciem pisania trzeba było poczekać, aż wszystkie pozycje w kolejce zakończą się. Upewnij się, że wywołasz 'task_done' na elementach, które otrzymujesz. – darvids0n

+0

Świetny pomysł! Kolejka jest wątkowo bezpieczna i jest znacznie ładniejsza niż list.append (dane) –

+0

Dodałem wywołanie 'task_done' zgodnie z sugestią darvids0n. Dzięki. – srgerg

1

będzie przechowywać powiedzieć listę list (bool, str), gdzie bool jest czy funkcja zakończy działanie i str jest wyjście. Każda funkcja blokuje listę mutexem, aby dołączyć wyjście (lub jeśli nie zależy ci na bezpieczeństwie wątku, pomiń to). Następnie wykonaj prostą pętlę odpytywania, sprawdzając, czy wszystkie wartości boolTrue, a jeśli tak, wykonaj połączenia save_to_disk.

0

Inną alternatywą byłoby zaimplementować klasę (wzięte z this answer), który używa threading.Lock(). Ma to tę zaletę, że może czekać na ItemStore, a save_to_disk może używać getAll, zamiast odpytywania kolejki. (Bardziej wydajne w przypadku dużych zestawów danych?)

Jest to szczególnie przydatne do zapisu w ustalonym przedziale czasu (tj. Co 30 sekund), a nie raz na sekundę.

class ItemStore(object): 
    def __init__(self): 
     self.lock = threading.Lock() 
     self.items = [] 

    def add(self, item): 
     with self.lock: 
      self.items.append(item) 

    def getAll(self): 
     with self.lock: 
      items, self.items = self.items, [] 
     return items 
Powiązane problemy