Параллельно: импортировать файл Python из папки одного уровня - PullRequest
0 голосов
/ 24 января 2019

У меня есть дерево каталогов

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)

Вот часть сообщения об ошибке, которое я получил

Traceback (последний вызов был последним):

Файл "/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'

Traceback (последний вызов был последним):

Файл "main.py", строка 12, в print (* ray.get (ids), sep = '\ n')

Файл "/Users/aptx4869/anaconda3/envs/p35/lib/python3.5/site-packages/ray/worker.py", строка 2377, в get повысить ценность ray.worker.RayTaskError: ray_worker (pid = 30025, host = AiMacbook)

Исключение: не удалось импортировать актера с именем MyWorker, поэтому он не может выполнить этот метод

Если я удаляю все операторы, связанные с ray, приведенный выше код работает нормально. Поэтому, я смело предполагаю, причина в том, что ray запускает каждого актора в новом процессе и только sys.path.append работает в основном процессе. Поэтому я добавляю следующий код в worker.py

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

Но все равно не работает: появляется то же сообщение об ошибке. Теперь у меня заканчиваются идеи, что мне делать?

1 Ответ

0 голосов
/ 24 января 2019

Вы правы в том, в чем проблема.

В вашем примере вы изменили sys.path в main.py, чтобы иметь возможность импортировать my_agent.my_worker и my_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, и это не удается, поскольку у конструктора актера еще не было возможности запустить.

Существует несколько возможных вариантоврешения здесь.

  1. Запустите скрипт с чем-то вроде

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

    (изнутри working_dir/).Это должно решить проблему, потому что в этом случае рабочие процессы разветвляются из процесса планировщика (который разветвляется из основного интерпретатора Python при вызове ray.init(), и поэтому переменная окружения будет наследоваться рабочими (этого не происходит)для 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() call) также работает по той же причине, что и выше.

  3. Рассмотрите возможность добавления setup.py и установки своего проекта в виде пакета Python, чтобы он автоматически находился на соответствующем пути.

...