0

我正在尝试在循环中运行自动生成的代码(可能不会终止),以进行遗传编程。我正在尝试为此使用多处理池,因为我不希望每次创建一个新进程的性能开销很大,并且如果它运行时间过长我可以终止池进程(我不能用线程做)。

本质上,我的程序是

if __name__ == '__main__':    
    pool = Pool(processes=1)            
    while ...:
        source = generate() #autogenerate code
        exec(source)
        print meth() # just a test, prints a result, since meth was defined in source
        result = pool.apply_async(meth)
        try:
            print result.get(timeout=3)  
        except:
           pool.terminate()

这是应该工作的代码,但不是,而是我得到

AttributeError: 'module' object has no attribute 'meth'

似乎 Pool 只看到 meth 方法,如果它是在最顶层定义的。任何建议如何让它运行动态创建的方法?

编辑:问题与进程完全相同,即

source = generated()
exec(source)
if __name__ == '__main__':    
    p = Process(target = meth)
    p.start()

工作,而

if __name__ == '__main__':    
    source = generated()
    exec(source)
    p = Process(target = meth)
    p.start()

没有,并因 AttributeError 而失败

4

3 回答 3

3

你读过编程指南吗?里面有很多关于全局变量的东西。在 Windows 下还有更多的限制。你没有说你在哪个平台上运行,但如果你在 Windows 下运行,这可能是问题所在。从上面的链接

全局变量

请记住,如果在子进程中运行的代码尝试访问全局变量,那么它看到的值(如果有)可能与调用 Process.start() 时父进程中的值不同.

但是,只是模块级常量的全局变量不会引起任何问题。

于 2009-09-27T20:33:21.563 回答
2

Process(通过 pool 或其他方式)不会有__name__of '__main__',所以它不会执行任何依赖于该条件的东西——当然包括exec你为了找到你meth的 所依赖的语句。

为什么您如此热衷于exec通过一个条件来保护它,根据设计,在您的子流程中将是错误的,但让该子流程依赖于(矛盾地!)执行该exec...?!真是让我脑洞大开……

于 2009-09-27T20:39:21.247 回答
0

正如我在上面评论的那样,您的所有示例都在我的 Linux 机器上按预期工作(Debian Lenny,Python2.5,处理 0.52,请参见下面的测试代码)。

您可以从一个进程传输到另一个进程的对象的窗口似乎有很多限制。阅读 Nick 指出的文档,似乎在窗口中缺少 fork 的操作系统将运行一个全新的 python 解释器导入模块和应该传递的 pickle/unpickle 对象。如果不能腌制它们,我希望您会遇到遇到的那种问题。

因此,一个完整的(非)工作示例可能对诊断有用。答案可能在你隐藏的无关紧要的事情中。

from processing import Pool
import os

def generated():
    return (
"""
def meth():
    import time
    starttime = time.time()
    pid = os.getpid()
    while 1:
        if time.time() - starttime > 1:
            print "process %s" % pid
            starttime = starttime + 1

""")


if __name__ == '__main__':
    pid = os.getpid()
    print "main pid=%s" % pid
    for n in range(5):
        source = generated() #autogenerate code
        exec(source)
        pool = Pool(processes=1)            
        result = pool.apply_async(meth)
        try:
            print result.get(timeout=3)  
        except:
           pool.terminate()

另一个建议是使用线程。的,即使您不知道生成的代码是否会停止或者生成的代码是否具有不同的嵌套循环,您也可以。循环完全没有限制,这正是使用生成器的一点(提取控制流)。我不明白为什么它不能适用于你正在做的事情。[同意独立进程可能更多的变化]见下面的例子。

import time

class P(object):
    def __init__(self, name):
        self.name = name
        self.starttime = time.time()
        self.lastexecutiontime = self.starttime
        self.gen = self.run()

    def toolong(self):
        if time.time() - self.starttime > 10:
            print "process %s too long" % self.name
            return True
        return False

class P1(P):
    def run(self):
        for x in xrange(1000):
            for y in xrange(1000):
                for z in xrange(1000):
                    if time.time() - self.lastexecutiontime > 1:
                        print "process %s" % self.name
                        self.lastexecutiontime = self.lastexecutiontime + 1
                        yield
        self.result = self.name.uppercase()

class P2(P):
    def run(self):
        for x in range(10000000):
            if time.time() - self.lastexecutiontime > 1:
                print "process %s" % self.name
                self.lastexecutiontime = self.lastexecutiontime + 1
                yield
        self.result = self.name.capitalize()

pool = [P1('one'), P1('two'), P2('three')]
while len(pool) > 0:
    current = pool.pop()
    try:
        current.gen.next()
    except StopIteration:
        print "Thread %s ended. Result '%s'" % (current.name, current.result) 
    else:
        if current.toolong():
            print "Forced end for thread %s" % current.name 
        else:
            pool.insert(0, current)
于 2009-09-27T21:51:38.613 回答