为什么 __bool__ 内置函数必须在 dask.delayed 对象上引发异常?
Why does __bool__ built-in function have to raise exception on dask.delayed objects?
我正在尝试 运行 使用 dask API 的任务的 DAG 用于我的特定应用程序。举一个人为的例子,我希望任务传递它们的 success/failure 标志并将它们用作其他任务的输入。
但是,dask 不允许我对延迟对象进行 __bool__
调用 (a and b
)。但它与按位布尔运算有何不同(即 a & b
)。
为什么实现为不支持?在本地修复它有多难?
我尝试深入研究源代码,但我无法理解 a & b
如何成功 return 是 ('and_', 'a', 'b'), 但 a and b
不 return 像 ('__bool__1', 'a'), ('__bool__2', 'b' ), ('and_', '__bool__1', '__bool__2').
我提供了最简单的源代码,可以重现问题。
import dask
from time import sleep
@dask.delayed
def task(x, cond):
if not cond:
return False
sleep(x)
return True
def run_graph():
task1_done = task(2, True)
task2_done = task(1, True)
task3_done = task(1, task2_done)
all_done = task1_done and task3_done
return all_done
if __name__ == '__main__':
done = run_graph()
dask.compute(done)
如果我们用 & 替换 and 操作,它工作正常。
all_done = task1_done & task3_done
这在这里可能不是问题,但我想使用 all()
和 any()
内置函数来获取延迟标志列表并在内部调用 __bool__
。
我个人并不详细了解 Dask,但我怀疑它只是在其对象上实现 __and__
。这根本不会将对象转换为布尔值。这与 and 或 etc 不同,它们首先将对象转换为布尔值。
这可以通过小测试快速测试class:
In [1]: class Test:
...: def __and__(self, other):
...: print("And called!")
...: return self
...: def __bool__(self):
...: print("Bool called!")
...: return True
...:
In [2]: a = Test()
In [3]: b = Test()
In [4]: a & b
And called!
Out[4]: <__main__.Test at 0x7f5eb58f4eb8>
In [15]: a and b
Bool called!
Out[5]: <__main__.Test at 0x7f5eb587e400>
根据我的理解,由于 Dask 确实进行了延迟求值,因此 __bool__
可能会强制立即求值工作良好,而 __and__
可以 return 一个惰性对象(因为它returns 是同一类型的对象,不是布尔值。
我正在尝试 运行 使用 dask API 的任务的 DAG 用于我的特定应用程序。举一个人为的例子,我希望任务传递它们的 success/failure 标志并将它们用作其他任务的输入。
但是,dask 不允许我对延迟对象进行 __bool__
调用 (a and b
)。但它与按位布尔运算有何不同(即 a & b
)。
为什么实现为不支持?在本地修复它有多难?
我尝试深入研究源代码,但我无法理解 a & b
如何成功 return 是 ('and_', 'a', 'b'), 但 a and b
不 return 像 ('__bool__1', 'a'), ('__bool__2', 'b' ), ('and_', '__bool__1', '__bool__2').
我提供了最简单的源代码,可以重现问题。
import dask
from time import sleep
@dask.delayed
def task(x, cond):
if not cond:
return False
sleep(x)
return True
def run_graph():
task1_done = task(2, True)
task2_done = task(1, True)
task3_done = task(1, task2_done)
all_done = task1_done and task3_done
return all_done
if __name__ == '__main__':
done = run_graph()
dask.compute(done)
如果我们用 & 替换 and 操作,它工作正常。
all_done = task1_done & task3_done
这在这里可能不是问题,但我想使用 all()
和 any()
内置函数来获取延迟标志列表并在内部调用 __bool__
。
我个人并不详细了解 Dask,但我怀疑它只是在其对象上实现 __and__
。这根本不会将对象转换为布尔值。这与 and 或 etc 不同,它们首先将对象转换为布尔值。
这可以通过小测试快速测试class:
In [1]: class Test:
...: def __and__(self, other):
...: print("And called!")
...: return self
...: def __bool__(self):
...: print("Bool called!")
...: return True
...:
In [2]: a = Test()
In [3]: b = Test()
In [4]: a & b
And called!
Out[4]: <__main__.Test at 0x7f5eb58f4eb8>
In [15]: a and b
Bool called!
Out[5]: <__main__.Test at 0x7f5eb587e400>
根据我的理解,由于 Dask 确实进行了延迟求值,因此 __bool__
可能会强制立即求值工作良好,而 __and__
可以 return 一个惰性对象(因为它returns 是同一类型的对象,不是布尔值。