我可以在Dask / Distributed中使用从.py文件导入的函数吗?

时间:2016-09-02 14:46:50

标签: python distributed-computing dask

我对序列化和导入有疑问。

  • 应该有自己的进口功能吗? like I've seen done with PySpark
  • 以下是完全错误的吗? mod.py是否需要成为conda / pip包? mod.py已写入共享文件系统。

In [1]: from distributed import Executor

In [2]: e = Executor('127.0.0.1:8786')

In [3]: e
Out[3]: <Executor: scheduler="127.0.0.1:8786" processes=2 cores=2>

In [4]: import socket

In [5]: e.run(socket.gethostname)
Out[5]: {'172.20.12.7:53405': 'n1015', '172.20.12.8:53779': 'n1016'}

In [6]: %%file mod.py
   ...: def hostname():
   ...:     return 'the hostname'
   ...: 
Overwriting mod.py

In [7]: import mod

In [8]: mod.hostname()
Out[8]: 'the hostname'

In [9]: e.run(mod.hostname)
distributed.utils - ERROR - No module named 'mod'

3 个答案:

答案 0 :(得分:5)

快速回答

将mod.py文件上传到所有工作人员。您可以使用您用于设置dask.distributed的任何机制来执行此操作,也可以使用upload_file方法

e.upload_file('mod.py')

或者,如果您的函数是在IPython中创建的,而不是作为模块的一部分,它将一直发送而没有问题。

长答案

这一切都与函数在Python中如何序列化有关。模块中的函数按其模块名称和函数名称

序列化
In [1]: from math import sin

In [2]: import pickle

In [3]: pickle.dumps(sin)
Out[3]: b'\x80\x03cmath\nsin\nq\x00.'

因此,如果客户端机器想要引用它发送的math.sin函数,那么就会发现这个字节串(你会注意到'math''sin'中的upload_file被埋在其他字节中)工人机器。工作人员看着这个字节串并说“好的,我想要的功能在这样一个模块中,让我去找我的本地文件系统。如果模块不存在则会引发错误,就像你上面收到的那样。

对于动态创建的函数(在IPython中创建的函数),它使用完全不同的方法,捆绑所有代码。这种方法通常很好。

一般来说,Dask假设工作者和客户端都具有相同的软件环境。通常,这主要由使用Docker之类的其他工具设置群集的人来处理。当您拥有更频繁更新的文件或脚本时,{{1}}等方法可以填补空白。

答案 1 :(得分:2)

要在群集上运行导入的功能,该功能在工作人员上不可用。在环境中,您还可以从导入的函数创建本地函数。然后cloudpickle将对此本地函数进行腌制。在Python 2中,您可以使用new.function实现此目标(请参阅new module)。对于Python 3,这可以通过types module实现,但我还没有尝试过。

上面的例子如下:

In [3]: import mod

In [4]: import new

In [5]: def remote(func):
   ...:     return new.function(func.func_code, func.func_globals, closure=func.func_closure)
   ...:

In [6]: e.run(remote(mod.hostname))
Out[6]: {'tcp://10.0.2.15:44208': 'the hostname'}

答案 2 :(得分:0)

将模块目录添加到PYTHONPATH为我工作