我试图在循环中运行自动生成的代码(可能无法终止),用于遗传编程。我正在尝试使用多处理池,因为我不希望每次都创建一个新进程带来巨大的性能开销,如果它运行时间太长(我不能使用线程),我可以终止池进程。
基本上,我的程序是
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方法。有任何建议如何让它运行动态创建的方法?
编辑: 问题与Process完全相同,即
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
而失败答案 0 :(得分:3)
您是否阅读过the programming guidelines?关于全局变量的内容很多。 Windows下有更多限制。您没有说明您正在运行哪个平台,但如果您在Windows下运行,则可能会出现问题。从上面的链接
全局变量
请记住,如果在子进程中运行的代码尝试访问全局变量,那么它看到的值(如果有)可能与Process.start时父进程中的值不同(被叫了。
但是,只是模块级常量的全局变量不会引起任何问题。
答案 1 :(得分:2)
Process
(通过池或其他方式)将不会__name__
'__main__'
,因此它不会执行任何取决于该条件的内容 - 包括{{1}当然,您依赖的语句是为了找到exec
。
为什么你如此热衷于让meth
受到一种条件的保护,按照设计,你的子流程中的IS会变错,但是这个子流程依赖 (矛盾的!)执行exec
......?!这真让人难以置信......
答案 2 :(得分:0)
正如我上面评论的那样,你所有的例子都在我的Linux盒子上运行(Debian Lenny,Python2.5,处理0.52,见下面的测试代码)。
对于可以从一个进程传输到另一个进程的对象,窗口似乎有很多限制。阅读Nick指出的文档,似乎在窗口中缺少os,它将运行一个全新的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)