Python传递函数句柄到线程

时间:2018-05-10 14:40:35

标签: multithreading python-2.7 asynchronous

我正在尝试使用python 2.7线程模块并行调用2个函数,为了让自己更容易,我编写了自己的AsycTask类。

class AsyncTask:
    def __init__(self, task, name="async-task", callback=None):
        self.task = task
        self.t = None
        if self.task is not None:
            if callback is not None:
                self.t = threading.Thread(target=lambda: [task(), callback()], name=name)
            else:
                self.t = threading.Thread(target=self.task, name=name)

    def start(self):
        if self.t is not None:
            self.t.start()
        else:
            Log.warn("Can't start async task: thread is None")

    def join(self):
        if self.t is not None:
            self.t.join()
        else:
            Log.warn("Can't join async task: thread is None")

但是当我传递函数句柄时,我得到了一些奇怪的结果。

在其他地方我有这个课程:

class Foo:
    def __init__(self, id):
        self.id = id

    def bar(self, args):
        result = None
        # do some stuff that takes a while
        time.sleep(10)

        Log.debug("bar() called in object %s" % self.id)
        return result

然后我创建了一个foo的列表

foos = []
foos.append(Foo("1"))
foos.append(Foo("2"))

并异步调用bar

results = []
tasks = []
for foo in foos:
    args = "some stuff"
    fn = foo.bar
    Log.debug("before async: " + str(foo))

    task = AsyncTask(lambda: [Log.debug("in async: " + str(fn)), results.append(fn(args))])
    tasks.append(task)
    task.start()

for task in tasks:
    task.join()

# process results

当我跑步时,我得到:

before async: <__main__.Foo instance at 0x7f9caef7e200>
before async: <__main__.Foo instance at 0x7f9caef7e248>
in async: <bound method Foo.bar of <__main__.Foo instance at 0x7f9caef7e248>>
in async: <bound method Foo.bar of <__main__.Foo instance at 0x7f9caef7e248>>
bar() called in object 2
bar() called in object 2

请注意,永远不会调用第一个bar()实例上的Foo,而是在第二个实例上调用两次。{/ p>

我没有大量的python经验,所以显然,我做错了什么,并且无法正确理解线程和函数如何在python中处理。

实现这一目标会有更多的pythonic方法吗?

1 个答案:

答案 0 :(得分:0)

您的设置类很好,您获得我们看不到的奇怪行为的原因很可能是您设置记录器的方式。在我按如下方式设置记录器之前,我的行为与您的行为相同:

import logging

logging.basicConfig()
log = logging.getLogger('log')

之后我得到以下内容:

before async: <__main__.Foo instance at 0x00000000028C9FC8>
before async: <__main__.Foo instance at 0x00000000028D5048>
<__main__.Foo instance at 0x00000000028C9FC8>
<__main__.Foo instance at 0x00000000028D5048>