title: Bandwidth throttling using Twisted
body: <p>I'm trying to set speed limits on downloading/uploading files and found that twisted provides <a href="http://twistedmatrix.com/documents/current/api/twisted.protocols.policies.ThrottlingFactory.html">twisted.protocols.policies.ThrottlingFactory</a> to handle this job, but I can't get it right. I set <code>readLimit</code> and <code>writeLimit</code>, but file is still downloading on a maximum speed. What am I doing wrong?</p>
  
  <pre class="lang-py prettyprint-override"><code>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()
  </code></pre>
  
  <p><strong>UPDATE</strong></p>
  
  <p>So sometime after I run it:</p>
  
  <pre><code>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()
      --- &lt;exception caught here&gt; ---
        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'
  </code></pre>
  
  <p>I see that I'm not supposed to assign producer like I do know <code>tsite.protocol.producer = producer</code>, I'm new to Twisted and I don't know how to do that another way.</p>