Использование многопроцессорной обработки Python при импорте модуля через путь к файлу - PullRequest
2 голосов
/ 06 мая 2009

Я пишу программу, которая импортирует модуль, используя путь к файлу, с функцией imp.load_source(module_name,module_path). Кажется, возникает проблема, когда я пытаюсь передать объекты из этого модуля в Process.

Пример:

import multiprocessing
import imp

class MyProcess(multiprocessing.Process):
    def __init__(self,thing):
        multiprocessing.Process.__init__(self)
        self.thing=thing
    def run(self):
        x=self.thing


if __name__=="__main__":
    module=imp.load_source('life', 'C:\\Documents and Settings\\User\\workspace\\GarlicSim\\src\\simulations\\life\\life.py')
    thing=module.step
    print(thing)
    p=MyProcess(thing)
    p.start()

Примечание: чтобы этот код работал, вы должны заменить параметры, которые я дал imp.load_source, на что-то другое: это должен быть какой-то файл Python на вашем компьютере, желательно не в той же папке. Затем в thing=module.step вместо шага вставьте некоторую случайную функцию или класс, определенный в этом файле .py.

Я получаю следующую трассировку:

<function step at 0x00D5B030>
Traceback (most recent call last):
  File "<string>", line 1, in <module>
  File "C:\Python26\lib\multiprocessing\forking.py", line 342, in main
    self = load(from_parent)
  File "C:\Python26\lib\pickle.py", line 1370, in load
    return Unpickler(file).load()
  File "C:\Python26\lib\pickle.py", line 858, in load
    dispatch[key](self)
  File "C:\Python26\lib\pickle.py", line 1090, in load_global
    klass = self.find_class(module, name)
  File "C:\Python26\lib\pickle.py", line 1124, in find_class
    __import__(module)
ImportError: No module named life

Так что мне делать?

EDIT:

Я использую Python 2.6.2c1 на Win XP.

Ответы [ 3 ]

1 голос
/ 06 мая 2009

Вероятно, это не работает из-за размещения кода импорта в основной блок. Код ниже работает на Windows XP, Python 2.6. Тогда жизненный модуль также будет импортирован в новый процесс.

import multiprocessing
import imp

class MyProcess(multiprocessing.Process):
  def __init__(self,thing):
    multiprocessing.Process.__init__(self)
    self.thing=thing
  def run(self):
    print("Exiting self.thing")
    self.thing()
    print("Finished")

life=imp.load_source('life', r'd:\temp5\life.py')

if __name__=="__main__":
  p=MyProcess(life.step)
  p.start()
0 голосов
/ 06 мая 2009

Я только что сделал следующее, работая на XP с Python 2.5 ...

D:\Experiments\ModuleLoading\test.py

import imp

if __name__=="__main__":
    module=imp.load_source('life', r'D:\Experiments\ModuleLoading\somefolder\life.py')
    thing=module.step
    print(thing)

D:\Experiments\ModuleLoading\somefolder\step.py

def step():
    return 'It works!'

... и запуск скрипта дает:

D:\jcage\Projects\Experiments\ModuleLoading>test.py
<function step at 0x00A0B470>

... так попробуйте сначала и убедитесь, что модуль может загружаться без многопроцессорной обработки?

[Редактировать] Хорошо, это определенно проблема с импортом в раздвоенный процесс. В документации есть несколько фрагментов, относящихся к windows :

Больше маринованности

Убедитесь, что все аргументы Process .__ init __ () доступны для выбора. Это означает, в частности, что связанные или несвязанные методы нельзя использовать непосредственно в качестве целевого аргумента в Windows - просто определите функцию и используйте ее вместо этого. Кроме того, если вы создаете подкласс Process, убедитесь, что экземпляры можно будет выбирать при вызове метода Process.start ().

Глобальные переменные

Имейте в виду, что если код, запущенный в дочернем процессе, пытается получить доступ к глобальной переменной, то значение, которое он видит (если он есть), может не совпадать со значением в родительском процессе в тот момент, когда Process.start ( ) назывался. Однако глобальные переменные, которые являются только константами уровня модуля, не вызывают проблем.

Безопасный импорт основного модуля

Убедитесь, что основной модуль может быть безопасно импортирован новым интерпретатором Python, не вызывая непреднамеренных побочных эффектов (таких как запуск нового процесса).

[Edit2] Есть ли причина, по которой вы не можете выполнить импорт в процессе? Я думаю, проблема в том, что когда вы запускаете новый процесс, он не работает в том же адресном пространстве, поэтому попытка доступа к функциям в исходном потоке не будет работать.

Вы можете сделать это для D:\Experiments\ModuleLoading\test.py вместо:

from multiprocessing import Process
import imp

class MyProcess(Process):
    def __init__(self):
        Process.__init__(self)

    def run(self):
        print 'run called...'
        module=imp.load_source('life', r'D:\Experiments\ModuleLoading\somefolder\life.py')
        print 'running...', module.step()

if __name__=="__main__":
    p=MyProcess()
    p.start()
0 голосов
/ 06 мая 2009

test.py в любой папке:

import multiprocessing
import imp

class MyProcess(multiprocessing.Process):
    def __init__(self,thing):
        multiprocessing.Process.__init__(self)
        self.thing=thing
    def run(self):
        print 'running...', self.thing()


if __name__=="__main__":
    module=imp.load_source('life', '/tmp/life.py')
    thing=module.step
    print(thing)
    p=MyProcess(thing)
    p.start()

life.py на /tmp:

def step():
    return 'It works!'

Бег test.py:

$ python test.py
<function step at 0xb7dc4d4c>
running... It works!

Я только что проверил, и это работает, так что вы, должно быть, делаете что-то еще не так. Пожалуйста, отредактируйте ваш вопрос и вставьте реальный код, который не работает.

Я использую Ubuntu Jaunty 9.04 с Python по умолчанию (Python 2.6.2 release26-maint, 19 апреля 2009, 01:56:41). Не знаю, если ваша проблема только для окон, потому что у меня нет окон для тестирования.

Это причина того, что искажение путей импорта является плохой идеей . Вы никогда не сделаете это правильно для всех платформ / сред, и ваши пользователи, вероятно, рассердятся. Лучше просто использовать Python способ поиска модулей, который заключается в размещении модуля на пути поиска модуля Python. Это будет работать везде везде.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...