Fujiao Liu
Fujiao Liu

Reputation: 2253

twisted defer make the assignment of class instance variables is invalid

I have a class A with two methods, method_one which uses a defer and method_two , in callback function I set a value to self.value and add it to defer's callback chain. but after that the self.value is still the original value in method_two. in short, the assignment of self.value in callback function is invalid.

from twisted.internet import utils, reactor
class A(object):

    def __init__(self):
        self.value = []

    def method_one(self):
        d = utils.getProcessOutput('/bin/sh', ('-c', 'ls /home')) # return a defer
        def set_self_value(result):
            self.value = result.split()  # assign result.split() to self.value
        d.addCallback(set_self_value)

    def method_two(self):
        print self.value  # it is still [] rather than result

a = A()
a.method_one()
a.method_two()
reactor.run()

output:
[]  # i expect self.value is ['lost+found', 'user']
lost+found
user

thanks in advance :-)

Upvotes: 3

Views: 457

Answers (1)

Ashwini Chaudhary
Ashwini Chaudhary

Reputation: 250961

The issue is that as the method_one is deferred, so, instead of calling set_self_value right away it first moves on to the next step a.method_two(), hence as at that time the value is not yet set you get an empty list.

To make sure method_two is called after method_one add it to the callback chain:

import twisted
from twisted.internet import utils
from twisted.internet import reactor


class A(object):

    def __init__(self):
        self.value = []

    def method_one(self):
        d = utils.getProcessOutput('/bin/sh', ('-c', 'ls /home'))
        def set_self_value(result):
            print 'called set'
            self.value = 100
        d.addCallback(set_self_value)
        d.addCallback(self.method_two)

    def method_two(self, *args): # *args required to handle the result
        print 'called two'
        print self.value

def main():
    a = A()
    a.method_one()


reactor.callWhenRunning(main)
reactor.run()

Output:

called set
called two
100

Upvotes: 3

Related Questions