2009-05-06 3 views
2

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

Пример:

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.

ответ

-1

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.04.2009, 01:56:41). Не знаю, является ли ваша проблема только оконной, потому что у меня нет окон, доступных для тестирования.

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

+0

Я скопировал свой код, изменяя только ' '/ TMP/life.py'' к'' TMP \\ life.py'', (я на Windows XP.) я получаю отслеживающий который, я думаю, такой же, как тот, что в моем вопросе, с этим модулем «pickle» в конце. Может быть, это происходит только в Windows? (Примечание: я использую Python 2.6.2c1) –

+0

Использование ubuntu Jaunty 9.04 с python по умолчанию (Python 2.6.2 release26-maint, 19.04.2009, 01:56:41). Не знаю, если это только окна, у меня нет окон, доступных для тестирования. Обратите внимание, что вы также можете использовать косые черты /tmp/life.py на окнах, не нужно менять их на обратные косые черты. – nosklo

-1

Я только что сделал следующее, работает на 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> 

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

[Изменить] Хорошо, так что это определенно проблема импорта в разветвленный процесс. Там в some bits and pieces in the documentation which are specific to windows:

Более picklability

Убедитесь, что все аргументы, чтобы процесс .__ инициализации __() являются пригодны для консервирования. Это означает, в частности, что связанные или несвязанные методы нельзя использовать непосредственно в качестве целевого аргумента в 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() 
+1

нужна обратная косая черта, но в вашем случае у вас нет побегов. 'D: \ foo \ bar \ quux \ life.py' становится D: ooar \ quux \ life.py. вместо этого используйте r'D: \ foo \ bar \ quux \ life.py ', который правильно становится D: \ foo \ bar \ quux \ life.py – SingleNegationElimination

+0

Хороший вопрос - сделаю коррекцию :-) –

+0

I' m получать ту же ошибку, пользуюсь ли я \ или/или \\. И, очевидно, модуль загружается в основной процесс: иначе 'print (thing)' не удастся. –

1

Вероятно, он не работает из-за размещения кода импорта в основной блок. Код ниже работает в 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()