2

我正在编写一个程序,它使用文件路径导入模块,函数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 文件,最好不在同一个文件夹中。然后, in thing=module.step,而不是 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

那我该怎么办?

编辑:

我在 Win XP 上使用 Python 2.6.2c1。

4

3 回答 3

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()
于 2009-05-06T17:03:28.817 回答
-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!

我刚刚测试并且它有效,所以你一定做错了什么。请编辑您的问题并粘贴不起作用的真实代码。

我正在使用带有默认 python 的 ubuntu Jaunty 9.04(Python 2.6.2 release26-maint,2009 年 4 月 19 日,01:56:41)。不知道您的问题是否仅限于 Windows,因为我没有可用于测试的 Windows。

这就是修改导入路径是一个坏主意的原因。您永远无法在所有平台/环境中正确使用它,您的用户可能会生气。最好只使用 python 查找模块的方式,即将模块放在 python 模块搜索路径上。这将在任何地方始终如一地工作。

于 2009-05-06T11:59:20.607 回答
-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>

...所以首先尝试并确保模块可以在没有多处理的情况下加载?

[编辑]好的,所以导入分叉进程肯定是个问题。文档中有一些特定于 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()
于 2009-05-06T12:50:49.280 回答