2009-05-06 81 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 

所以,我该怎么办?

编辑:

我使用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,2009年4月19日,01:56:41)。不知道你的问题是否仅限于Windows,因为我没有可用的窗口来测试。

这是一个原因,与进口路径混合是一个坏主意。你永远无法适应所有的平台/环境,你的用户可能会生气。更好的方法是使用python查找模块的方式,即将模块放在python模块搜索路径中。这将始终贯穿始终。

+0

我复制你的代码,只有改变' '的/ tmp/life.py'`到`' TMP \\ life.py'`,(我在Windows XP上。) 我得到一个回溯我认为这与我的问题是一样的,最后是“pickle”模块。也许它只发生在Windows上? (注意:我正在使用Python 2.6.2c1) – 2009-05-06 12:05:04

+0

使用带默认python的ubuntu Jaunty 9.04(Python 2.6.2 release26-maint,Apr 19 2009,01:56:41)。不知道它是否仅限于Windows,我没有可用于测试的窗口。请注意,您也可以在Windows上使用正斜杠/tmp/life.py,无需将其更改为反斜杠。 – nosklo 2009-05-06 12:14:46

-1

我刚刚做了以下,与Python 2.5在XP上运行...

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

确保所有参数流程.__的init __()是picklable。这意味着,特别是绑定或未绑定的方法不能直接用作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

也许它不会因为导入代码放置到主块的工作。 以下代码适用于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() 
相关问题