2012-10-24 13 views
10

Próbuję ustawić ograniczenia prędkości pobierania/przesyłania plików i okazało się, że skręcony zapewnia twisted.protocols.policies.ThrottlingFactory do obsługi tego zadania, ale nie mogę go naprawić. Ustawiłem readLimit i writeLimit, ale nadal pobierano plik na maksymalnej prędkości. Co ja robię źle?Ograniczanie przepustowości za pomocą Twisted

from twisted.protocols.basic import FileSender 
from twisted.protocols.policies import ThrottlingFactory 
from twisted.web import server, resource 
from twisted.internet import reactor 
import os 

class DownloadPage(resource.Resource): 
    isLeaf = True 

    def __init__(self, producer): 
     self.producer = producer 

    def render(self, request): 
     size = os.stat(somefile).st_size 
     request.setHeader('Content-Type', 'application/octet-stream') 
     request.setHeader('Content-Length', size) 
     request.setHeader('Content-Disposition', 'attachment; filename="' + somefile + '"') 
     request.setHeader('Accept-Ranges', 'bytes') 

     fp = open(somefile, 'rb') 
     d = self.producer.beginFileTransfer(fp, request) 

     def err(error): 
      print "error %s", error 

     def cbFinished(ignored): 
      fp.close() 
      request.finish() 
     d.addErrback(err).addCallback(cbFinished) 

     return server.NOT_DONE_YET 


producer = FileSender() 
root_resource = resource.Resource() 
root_resource.putChild('download', DownloadPage(producer)) 
site = server.Site(root_resource) 
tsite = ThrottlingFactory(site, readLimit=10000, writeLimit=10000) 
tsite.protocol.producer = producer 
reactor.listenTCP(8080, tsite) 
reactor.run() 

UPDATE

Więc kiedyś po biegnę go:

2012-10-25 09:17:03+0600 [-] Unhandled Error 
Traceback (most recent call last): 
     File "/home/chambylov/environments/transfer/local/lib/python2.7/site-packages/twisted/application/app.py", line 402, in startReactor 
     self.config, oldstdout, oldstderr, self.profiler, reactor) 
     File "/home/chambylov/environments/transfer/local/lib/python2.7/site-packages/twisted/application/app.py", line 323, in runReactorWithLogging 
     reactor.run() 
     File "/home/chambylov/environments/transfer/local/lib/python2.7/site-packages/twisted/internet/base.py", line 1169, in run 
     self.mainLoop() 
     File "/home/chambylov/environments/transfer/local/lib/python2.7/site-packages/twisted/internet/base.py", line 1178, in mainLoop 
     self.runUntilCurrent() 
    --- <exception caught here> --- 
     File "/home/chambylov/environments/transfer/local/lib/python2.7/site-packages/twisted/internet/base.py", line 800, in runUntilCurrent 
     call.func(*call.args, **call.kw) 
     File "/home/chambylov/environments/transfer/local/lib/python2.7/site-packages/twisted/protocols/policies.py", line 334, in unthrottleWrites 
     p.unthrottleWrites() 
     File "/home/chambylov/environments/transfer/local/lib/python2.7/site-packages/twisted/protocols/policies.py", line 225, in unthrottleWrites 
     self.producer.resumeProducing() 
     File "/home/chambylov/environments/transfer/local/lib/python2.7/site-packages/twisted/protocols/basic.py", line 919, in resumeProducing 
     self.consumer.unregisterProducer() 
     File "/home/chambylov/environments/transfer/local/lib/python2.7/site-packages/twisted/web/http.py", line 811, in unregisterProducer 
     self.transport.unregisterProducer() 
     File "/home/chambylov/environments/transfer/local/lib/python2.7/site-packages/twisted/protocols/policies.py", line 209, in unregisterProducer 
     del self.producer 
    exceptions.AttributeError: ThrottlingProtocol instance has no attribute 'producer' 

widzę, że nie mam przypisać producentowi jak wiem tsite.protocol.producer = producer, jestem nowy Pokręcony i nie wiem, jak to zrobić w inny sposób.

+1

Patrząc na źródło istnieje linia, 'lo g.msg ("Dławienie czyta% s"% self) "czy możesz sprawdzić, czy jest on rejestrowany? – John

+0

to nie loguje * throttleReads metod, ale robi * throttleWrites: 'Przepustnica zapisuje na ' –

+0

Podejrzewam, że musisz wstawić obiekt dławiący pomiędzy 'file' czytanym i i 'render()', a może lepiej między 'reaktorem' a twoją instancją' render/DownloadPage'. Teraz wydaje się, że przekazujesz 'producer' zarówno do obiektów DownloadPage, jak i Throttling, to nie wydaje się właściwe. –

Odpowiedz

1

Every producer needs (eventually) to be registered with whatever you want to consume the data. Nie widzę tutaj żadnej rejestracji. Może to jest problem, który masz?

Twisted był używany w niektórych projektach typu big-time, takich jak Friendster, ale wszystkie wywołania zwrotne nie są zgodne ze zwykłym sposobem pisania w pythonie (i mam pewne doświadczenie z programowaniem funkcjonalnym). Przełączyłem się na gevent.

Jeśli pracujesz z bibliotekami gevent, wiele detali (wywołań zwrotnych/generatorów, które dostarczają asynchronicznej funkcjonalności) jest wyodrębnionych, dzięki czemu można zwykle uciec z małpiącą łataniem twojego kodu i zapisaniem go w zwykłym obiekcie zorientowany styl, do którego jesteś przyzwyczajony. Jeśli pracujesz nad projektem z kimś, kto nie znał ciężkiego języka wywołującego zwroty, takiego jak js/sepia, założę się, że docenią geentę na przekręcony.

+0

Ta odpowiedź byłaby lepsza (godna przegranej) bez bezcelowego strzelania. Nie wspominasz nawet, jak geent radzi sobie z kontrolą przepływu. – Glyph

+0

@Glyph naprawdę przepraszam za to - mam nadzieję, że usunąłem to świństwo. Mnóstwo szacunku dla (genialnych) ludzi, którzy rozwinęli Twisted - nie chciałem obrazy. Być może tylko niektóre pozostałości po moich złych doświadczeniach. :) – egbutter

+0

Dzięki za modyfikację - ale nadal nie wyjaśniasz, jak geent faktycznie radzi sobie z konkretnym zagadnieniem kontroli przepływu :). – Glyph

1

Jak powiedział egbutter, musisz zarejestrować producenta. Więc zamiast tego:

tsite.protocol.producer = producer 

trzeba wezwać registerProducer sposób wyraźnie:

tsite.protocol.registerProducer(...) 

lub, jeśli używasz FileSender jako producent, zadzwoń do swojego beginFileTransfer metody , w naszym przypadku:

file_to_send = open(...) 
producer.beginFileTransfer(file_to_send, tsite.protocol) 
Powiązane problemy