2012-02-05 199 views
4

所以,这是我的情况。'if __name__ =='后面的任何内容__main__“:'不执行

我在Eclipse中使用PyDev,Windows中的Python解释器版本2.7.2。

我正在使用内置的多处理库试图分离出一堆进程来并行化一个非常计算密集型的循环。我看了看教程说来使用,

if __name__ == "__main__": 

,以防止它产卵关闭接近无限的流程和把我的系统瘫痪,本质上。

问题是,我从一个模块调用它,而不是我的主脚本;因此,在EVER执行后没有任何东西。完全没有并行的机会。当然,如果我删除它,我会收到杀死执行代码的机器的infiniprocess垃圾邮件。

作为参考的缘故,这里的相关代码:

from tribe import DataCache 
from tribe import WorldThread 
from tribe import Actor 
from time import sleep 
import multiprocessing 

class World: 
def __init__(self,numThreads,numActors,tickRate): 
    print "Initalizing world..." 
    self.cache = DataCache.DataCache() 
    self.numThreads = numThreads 
    self.numActors = numActors 
    self.tickRate = tickRate 
    self.actors = [] 
    self.processes = [] 
    for i in range(numActors): 
     self.actors.append(Actor.Actor("test.xml",self.cache)) 
    print "Actors loaded." 
def start_world(self): 
    print "Starting world" 
    run_world = True; 
    while run_world: 
     self.world_tick() 
     sleep(2) 

def world_tick(self): 
     if __name__ == '__main__': 
      print "World tick" 
      actor_chunk = len(self.actors)/self.numThreads 
      if len(self.processes)==0: 
       for _ in range(self.numThreads): 
        new_process = multiprocessing.Process(WorldThread.WorldProcess.work, args=(_, self.actors[_*actor_chunk,(_+1)*actor_chunk])) 

而且它调用类:

class WorldProcess(): 
def __init__(self): 
    print "World process initilized." 
    ''' Really, I'm not sure what kind of setup we'll be doing here yet. ''' 
def work(self, process_number, actors): 
    print "World process" + str(process_number) + " running." 
    for actor in actors: 
     actor.tick() 
    print "World process" + str(process_number) + " completed." 

我是在我的评估纠正,如果整个 ==“主要“:只有在可执行脚本本身包含它时才检查是否有效?如果是这样,你如何安全地从模块中分离进程?如果没有,为什么它不在这里工作?

+0

调用'multiprocessing.Process(WorldThread.WorldProcess.work,...)'看起来很可疑。你正在调用一个类的实例方法,但我不认为多处理模块会为你实例化它。您也没有像文档中指出的那样使用关键字参数调用方法 - “Process”的第一个参数是不应该被忽略的参数。 – millimoose 2012-02-05 22:36:56

+0

哎呀,我肯定在那里犯了一个错误 - 我应该把目标= WorldThread.WorldProcess ...等等。另外,我见过的所有例子(并且承认它们是有限的)已经调用了来自导入的方法类没有实例化这些类,所以我怀疑这是问题。然而,我遇到的真正问题是,name == main检查后面的任何内容都没有执行。我真正想要的是对这一点的澄清,以及如何从模块内安全地进行多进程。 – Laereom 2012-02-05 22:50:07

+3

'if __name __ ==“__ main __”'是您在将成为入口点的脚本的根级别执行的操作。它是一种只有在脚本直接执行时才能做的事情。 – jdi 2012-02-05 22:50:55

回答

2

要控制的过程的量,使用Pool类从multiprocessing

from multiprocessing import Pool 
p = Pool(5) 
def f(x): 
    return x*x 
p.map(f, [1,2,3]) 

(编辑:如每评论,这对于池类只是HOWTOsee更多)

使用__name__不是必需的,因为您明确地通过Process实际python函数运行。

此:

def world_tick(self): 
    if __name__ == '__main__': 
     print "World tick" 
     actor_chunk = len(self.actors)/self.numThreads 
     if len(self.processes)==0: 
      for _ in range(self.numThreads): 
       new_process = multiprocessing.Process(WorldThread.WorldProcess.work, args=(_, self.actors[_*actor_chunk,(_+1)*actor_chunk])) 

是非常糟糕的。简化它。

一个更好的方式将是:

class WorkArgs(object): 
    ... many attributes follow ... 

def proc_work(world_thread, work_args): 
    world_thread.WorldProcess.work(work_args.a, work_args.b, ... etc) 

p = Pool(5) 
p.map(proc_work, [(world_thread, args0), (world_thread, args1), ...]) 

希望这有助于!

作为一个便笺,酸洗您的论点并将它们传递给其他进程将导致导入您的模块。所以,最好确保你的模块不会执行任何分叉/魔术/工作,除非它被告知(例如,只有函数/类定义或魔术,而不是实际的代码块)。

+0

你的第一个例子用'AttributeError的崩溃了:“模块”对象有f'' – phihag 2012-02-05 22:59:35

+0

没有属性”关于这一点:http://docs.python.org/library/multiprocessing.html#introduction – Ohad 2012-02-05 23:00:56

+0

啊,我喜欢它。检查你的代码,它看起来像p.map是实际执行上面设置的东西,相当于在我的代码中实例化multiprocessing.process的调用(尽管更好),其中你放入函数调用,然后传递一个元组列表,每个元组包含一个要使用的WorldThread实例和要使用的参数。我的评估是否正确? – Laereom 2012-02-05 23:11:25

2

添加此作为一个答案,因为它是在注释:

if __name__ == "__main__"是你在那将是一个入口点的脚本的根级别做一些事情。它是一种只有在脚本直接执行时才能做的事情。

如果你有一个脚本,它的入口点,你的名字==主。在一个你想要多进程的模块中,你只需循环和启动你的进程就像循环和启动线程一样。

相关问题