2009-05-06 80 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() 
相關問題