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(プールまたはその他を介して)__name__of'__main__'がないため、その条件に依存するものは何も実行されません-もちろん、execを見つけるために依存するステートメントを含みますmeth

exec設計上、サブプロセスで IS が false になるという条件でそれを保護することに熱心なのはなぜですかexec? 本当に頭がおかしい…。

于 2009-09-27T20:39:21.247 に答える
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)
于 2009-09-27T21:51:38.613 に答える