2010-07-21 18 views
6

sahip 1 günlük deneyim ben tcp müşteriye cevapta gönderme mesajı ayarlamaya çalışın:Python twisted: nasıl planlanır? Twisted içinde

import os, sys, time 
from twisted.internet import protocol, reactor 

self.scenario = [(1, "Message after 1 sec!"), (4, "This after 4 secs"), (2, "End final after 2 secs")] 
for timeout, data in self.scenario: 
     reactor.callLater(timeout, self.sendata, data) 
     print "waited %d time, sent %s\n"%(timeout, data) 

Şimdi mesajları gönderir, ama 2 sorunları var:
1) "zaman aşımı" "den gidiyor şimdi "ve önceki her görev tamamlandıktan sonra onu saymak istiyorum (önceki mesaj gönderildi)
2) Tüm mesajlar gönderildikten sonra bağlantıyı nasıl kapatacağımı bilmiyorum. callLater s sonra self.transport.loseConnection() yerleştirirseniz hemen bağlantıyı kapatır.

Bir önceki denemede reactor.callLater, ancak self.transport.write() ve time.sleep(n)for döngüsünde kullanmadım. Bu durumda tüm mesajlar tüm zaman aşımları geçtikten sonra birlikte gönderildi ... İstediğim bir şey değil.
İstemci bağlantısı için beklemek, zaman aşımı1 beklemek ve ileti1, bekle zaman aşımı2 ve ileti2, ... göndermek vb. Son mesajdan sonra - bağlantıyı kapatın.

cevap

8

Twisted ile çalışırken fark edilmesi gereken en önemli şey, 'un hiçbir şeyin hiçbir şey için beklememesidir. reactor.callLater()'u aradığınızda, reaktörden daha sonra bir şey çağırmasını istiyorsunuz, şimdi değil. Çağrı hemen biter (çağrı planlandıktan sonra,'dan önce çalıştırılmıştır.) Sonuç olarak, print ifadeniz bir yalandır: timeout saatini beklemediyseniz; hiç beklemedin.

Bunu birden çok yolla düzeltebilir ve gerçekte ne kullanmak istediğinize bağlı olarak kullanabilirsiniz. İkinci görevin 'u başlatmasından sonra dört saniye başlamasını istiyorsanız, ilk görevin gecikmesini (timeout değişkenini) ikinci görevin gecikmesine ekleyebilirsiniz. Bununla birlikte, ilk görev, planladığınız zaman tam olarak başlamayabilir; Twisted eğer daha erken başlamak için çok meşgulse, daha sonra başlayabilir. Ayrıca, göreviniz uzun sürerse, ikinci görev başlamadan gerçekten yapılmayabilir.

İlk görev için ikinci görevi zamanlamak yerine, ilk görev için daha sık kullanılan yöntemdir. İlk görev bittikten dört saniye sonra (ilk görevin sonunda reactor.callLater()'u arayarak) ya da ilk görevin başlamasından dört saniye sonra ('u ilk görevin başlangıcında başlayarak) veya daha fazlasını gerçekleştirebilirsiniz. ne zaman başlaması gerektiğini belirleyen karmaşık hesaplamalar, geçen sürenin izlenmesi.

Twisted beklemede hiçbir şey fark etmediğinizde, tüm zamanlanmış görevleri gerçekleştirdiğinizde bağlantıyı kapatmakla uğraşmak kolaylaşır: yalnızca son görev çağrınızı self.transport.loseConnection() alırsınız. Daha karmaşık durumlar için, Deferred s'yi birbirine zincirlemek veya loseConnection()'u, tüm bekletme görevleri tamamlandığında, tam olarak ardışık olmadıklarında bile bitirmek için kullanmak üzere DeferredList kullanabilirsiniz. işe yaramadı "uyur" neden bu anlaşma için

+0

sayesinde, şimdi anladım. Önceki reactor.callLater() 'ın sonunda reactor.callLater() zamanlama ile bir örnek verebilir misiniz? – DominiCane

+0

Sadece 'self.sendata (data)' olarak adlandırılan bir işlevi tanımlayın ve sonra bir sonraki geri arama için 'reactor.callLater()' işlevini çağırın ve bu işlevi 'self.sendata yerine ilk' reakctor.callLater() 'öğesine iletin. –

4

Final çözüm ..

import os, sys, time 
from twisted.internet import protocol, reactor 
import itertools 

def sendScenario(self): 
    def sendelayed(d): 
     self.sendata(d) 
     self.factory.out_dump.write(d) 
     try: 
      timeout, data = next(self.sc) 
      reactor.callLater(timeout, sendelayed, data) 
     except StopIteration: 
      print "Scenario completed!" 
      self.transport.loseConnection() 

    self.scenario = [(1, "Message after 1 sec!"), (4, "This after 4 secs"), (2, "End final after 2 secs")] 
    self.sc = iter(self.scenario) 
    timeout, data = next(self.sc) 
    reactor.callLater(timeout, sendelayed, data) 
+0

Sadece fyi: 'self.scenario .__ iter __()' -> 'iter (self.scenario)', 'self.sc.next() '->' next (self.sc) '(2.6'dan beri düşünüyorum) –

+0

Teşekkürler, değişti. – DominiCane

İlgili konular