Peter Bejan
Peter Bejan

Reputation: 425

object has no attribute while trying to define thread

This is the code:

class foo:
    def levelOne(self):
        def worker(self, i):
            print('doing hard work')
        def writer(self):
            print('writing workers work')

session = foo()

i=0
threads = list()
for i in range(0,5):
    thread = threading.Thread(target=session.levelOne.worker, args=(i,))
    thread.start()
    threads.append(thread)

writerThread = threading.Thread(target=session.levelOne.writer)
writerThread.start()

for thread in threads:
    thread.join()

writerThread.join()

5 workers should do the job and the writer should collect their results.

The error I get is: session object has no attribute worker

workers are actually testers that do a certain work in different "areas" while writer is keeping track of them without making my workers return any result. It's important for this algorithm to be divided on layers like "levelOne", "levelTwo" etc. because they will all work together. This is the main reason why I keep the threading outside the class instead of the levelOne method.

please help me understand where I'm wrong

Upvotes: 0

Views: 3088

Answers (1)

bruno desthuilliers
bruno desthuilliers

Reputation: 77912

You certainly dont have "session object has no attribute worker" as error message with the code you posted - the error should be "'function' object has no attribute 'worker'". And actually I don't know why you'd expect anything else - names defined within a function are local variables (hint: python functions are objects just like any other), they do not become attributes of the function.

It's important for this algorithm to be divided on layers like "levelOne", "levelTwo"

Well, possibly but that's not the proper design. If you want foo to be nothing but a namespace and levelOne, levelTwo etc to be instances of some type having bot a writer and worker methods, then you need to 1/ define your LevelXXX as classes, 2/ build instances of those objects as attributes of your foo class, ie:

class LevelOne():
    def worker(self, i):
       # ...
    def writer(self):
       # ...


class foo():
    levelOne = LevelOne()

Now whether this is the correct design for your use case is not garanteed in any way, but it's impossible to design a proper solution without knowing anything about the problem...

If it's possible could you explain why trying to access workers and writer as shown in question's code is bad design?

Well, for the mere reason that it doesn't work, to start with, obviously xD.

Note that you could return the "worker" and "writer" functions from the levelOne method, ie:

class foo:
    def levelOne(self):
        def worker(self, i):
            print('doing hard work')
        def writer(self):
            print('writing workers work')

        return worker, writer


session = foo()
worker, writer = session.levelOne()

# etc

but this is both convoluted (assuming the point is to let worker and writer share self, which is much more simply done using a proper LevelOne class and making worker and writer methods of this class) and inefficient (def is an executable statement, so with your solution the worker and writer functions are created anew - which is not free - on each call).

Upvotes: 2

Related Questions