并行:从同级文件夹导入python文件

时间:2019-01-24 01:11:47

标签: python parallel-processing distributed-system ray

我有一个目录树

working_dir\
    main.py
my_agent\
    my_worker.py
my_utility\
    my_utils.py

每个文件中的代码如下

""" main.py """

import os, sys
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))

from my_agent.my_worker import MyWorker
import ray

ray.init()
workers = [MyWorker.remote(i) for i in range(10)]
ids = [worker.get_id.remote() for worker in workers]
# print(*ids, sep='\n')
print(*ray.get(ids), sep='\n')
""" worker.py """
from my_utility import my_utils
import ray

@ray.remote
class MyWorker():
    def __init__(self, id):
        self.id = id

    def get_id(self):
        return my_utils.f(self.id)
""" my_utils.py """
def f(id):
    return '{}: Everything is fine...'.format(id)

这是我收到的错误消息的一部分

  

回溯(最近通话最近一次):

     

文件“ /Users/aptx4869/anaconda3/envs/p35/lib/python3.5/site-packages/ray/function_manager.py”,行616,位于fetch_and_register_actor中       unpickled_class = pickle.loads(pickled_class)

     

文件“ /Users/aptx4869/anaconda3/envs/p35/lib/python3.5/site-packages/ray/cloudpickle/cloudpickle.py”,第894行,在子导入中       导入(名称)

     

ImportError:没有名为“ my_utility”的模块

     

回溯(最近通话最近一次):

     

文件“ main.py”,第12行,在       打印(* ray.get(ids),sep ='\ n')

     

文件“ /Users/aptx4869/anaconda3/envs/p35/lib/python3.5/site-packages/ray/worker.py”中的第2377行       提高价值   ray.worker.RayTaskError:ray_worker(pid = 30025,host = AiMacbook)

     

异常:名称为MyWorker的演员无法导入,因此无法执行此方法

如果我删除与ray相关的所有语句,则上面的代码可以正常工作。因此,我大胆地猜测原因是ray在新流程中运行每个actor和sys.path.append仅在主要过程中起作用。因此,我将以下代码添加到worker.py

import os, sys
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))

但是它仍然不起作用:显示相同的错误消息。现在我没办法了,该怎么办?

1 个答案:

答案 0 :(得分:2)

您对问题是正确的。

在您的示例中,您在sys.path中修改了main.py,以便能够导入my_agent.my_workermy_utility.my_utils

但是,此路径更改不会传播到工作进程,因此,如果要运行像这样的远程功能

@ray.remote
def f():
    # Print the PYTHONPATH on the worker process.
    import sys
    print(sys.path)

f.remote()

您会看到工作服务器上的sys.path不包括您添加的父目录。

在工作程序上修改sys.path的原因(例如,在MyWorker构造函数中)不起作用的原因是,MyWorker类定义被腌制并运送到工作程序。然后,工作人员对其进行解除锁定,并且解除对类定义的限制的过程需要导入my_utils,但这失败了,因为actor构造函数还没有运行的机会。

这里有两种可能的解决方案。

  1. 以类似的方式运行脚本

    PYTHONPATH=$(dirname $(pwd)):$PYTHONPATH python main.py
    

    (来自working_dir/中)。那应该可以解决问题,因为在这种情况下,工作进程是从调度程序进程派生的(当您调用ray.init()时,它是从主Python解释器派生的,因此环境变量将由工作程序继承(这不是' sys.path不会发生,大概是因为它不是环境变量。

  2. 看起来像添加行

    parent_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
    os.environ["PYTHONPATH"] = parent_dir + ":" + os.environ.get("PYTHONPATH", "")
    
    main.py中(在ray.init()调用之前)中的

    也与上述相同的原因起作用。

  3. 考虑添加一个setup.py并以Python软件包的形式安装您的项目,以使其自动位于相关路径上。