0

我正在尝试使用 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实例上永远不会调用它,而在第二个实例上它会被调用两次。

我没有大量的 python 经验,所以很明显,我做错了什么,不能正确理解线程和函数句柄在 python 中的工作方式。

什么是更 Pythonic 的方式来实现这一点?

4

1 回答 1

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>
于 2018-05-10T15:52:06.240 回答