[Twisted-Python] Trying to proxy through multiple IPs

Michael ms at cerenity.org
Tue Nov 4 06:25:28 EST 2008


Just going back to the closure issue, it's probably worth mentioning an issue 
with closures that people used to them in other languages sometimes get 
caught by.

On Tuesday 04 November 2008 10:04:43 Andrew Bennetts wrote:
> class ProxyFactory(http.HTTPFactory):
>
>     def __init__(self, ip):
>          self.protocol = Proxy
>          self.protocol.requestFactory = ProxyRequest
>          self.protocol.requestFactory.bindIP = ip

This is also safer than using what python views as a closure - because 
closures in python don't capture all the free variables unlike closures in 
other languages. 

The original poster's code...

> class ProxyFactory(http.HTTPFactory):
>     def class_factory(self, bindIP):
>         def closure(ip):
>             klass2 = ProxyRequest

... is not safe, due to the ProxyRequest free variable.


Example:

def ProxyRequest(who): print "hello", who

class demo(object):
    def __init__(self, f="world"):
        def mkClosure(f):
            def X():
                ProxyRequest(f)
            return X
        self._C = mkClosure(f)
    def C(self):
        (self._C)()

X=demo()
X.C()

def ProxyRequest(who):
   print "game over"

X.C()

Running this results in:
hello world
game over

In most other languages with closures I've used this would result in:

hello world
hello world

This issue remains in python 3.0, for those wondering.

The only safe way of doing this is to capture a local value and use that 
instead:

class demo(object):
    def __init__(self, f="world"):
        pr = proxyRequest
        def closure(f):
            def X():
                pr(f)
            return X
        self._C = closure(f)

... if you have to use a closure.


Michael.
-- 
http://yeoldeclue.com/blog




More information about the Twisted-Python mailing list