0

一連のタスクを受け取り、それらをクラスター上の異なるスレッドまたは異なるノードに分散する Python コードがあります。driver.py私はいつも2 つのコマンド ライン引数を取るメイン スクリプトを書くことになります:--run-all--run-task. driver.py --run-task1 つ目は、すべてのタスクを反復処理し、引数として渡された各タスクで呼び出す単なるラッパーです。例:

== driver.py ==
# Determine the current script
DRIVER = os.path.abspath(__file__)
(opts, args) = parser.parse_args()
if opts.run_all is not None:
  # Run all tasks
   for task in opts.run_all.split(","):
     # Call driver.py again with a specific task
     cmd = "python %s --run-task %s" %(DRIVER, task)
     # Execute on system
     distribute_cmd(cmd)
elif opts.run_task is not None:
  # Run on an individual task
  # code here for processing a task...

次に、ユーザーは次のように呼び出します。

$ driver.py --run-all task1,task2,task3,task4

そして、各タスクが分散されます。

この関数distribute_cmdは、シェル実行可能コマンドを受け取り、システム固有の方法でノードまたはスレッドに送信します。driver.py独自の名前を見つけて自分自身を呼び出さなければならない理由はdistribute_cmd、実行可能なシェル コマンドが必要だからです。たとえば、関数名を取ることはできません。

この考慮事項により、2 つのモードを持ち、それ自体を呼び出さなければならないドライバー スクリプトの設計にたどり着きました。これには 2 つの複雑な問題があります。(1) スクリプトはそれ自身のパスを経由して見つける必要が__file__あり、(2) これを Python パッケージにする場合、どこdriver.pyに行くべきかが不明です。これは実行可能なスクリプトであることを意図していますが、setup.py'sに入れるとscripts=、スクリプトがどこにあるかを見つける必要があります ( Python distutils の setup.py からスクリプト ディレクトリを見つける正しい方法を参照してください)。これは良い解決策ではないようです。

これに代わるデザインは何ですか?タスクの分散は、文字列として に渡すことができる実行可能なコマンドになる必要があることに注意してdistribute_cmdください。ありがとう。

4

1 に答える 1

1
  • あなたが探しているのは、必要なことをすでに正確に実行するライブラリFabricですCelery
  • ノードを使用していない場合は、使用することをお勧めしmultiprocessingます。
  • これはこれと少し似た質問です

リモートで実行できるようにするには、次のいずれかが必要です。

  • sshボックスへのアクセス。その場合Fabric、コマンドを送信するために使用できます。
  • サーバー、SocketServer、tcp サーバー、または接続を受け入れるものなら何でも。
  • データを待機するエージェントまたはクライアント。エージェントを使用している場合は、メッセージにブローカーを使用することもできます。Celeryでは、配管の一部を実行できます。一方の端のputsメッセージをキューに入れ、もう一方の端のgetsメッセージをキューから出すことができます。メッセージが実行するコマンドである場合、エージェントはos.system()コールを実行できます。subprocess.Popen()

セロリの例:

 import os
 from celery import Celery
 celery = Celery('tasks', broker='amqp://guest@localhost//')
 @celery.task
 def run_command(command):
    return os.system(command)

次に、キューにバインドしてタスクの実行を待機するワーカーが必要になります。詳細については、ドキュメントを参照してください

生地の例:

コード:

from fabric.api import run
def exec_remotely(command):
   run(command)

呼び出し:

$ fab exec_remotely:command='ls -lh'

詳細については、ドキュメントを参照してください

バッチシステムの場合: 質問に戻るには...

  • distribute_cmd呼び出すものですbsub somescript.sh
  • 同じスクリプトを他のパラメーターで再実行するため、ファイルのみを見つける必要があります
  • 上記の理由により、正しいdistutilsスクリプトを提供する際に問題が発生する可能性があります。

このデザインに疑問を投げかけましょう。

  • なぜ同じスクリプトを使用する必要があるのですか?
  • あなたのドライバーはスクリプトを書いて bsub を呼び出すことができますか?
  • 一時ファイルを使用できますか?
  • すべてのノードが実際にファイルシステムを共有していますか?
  • ファイルがノードに存在することをどのように知ることができますか?

例:

TASK_CODE = {
   'TASK1': '''#!/usr/bin/env python
#... actual code for task1 goes here ...
''',
   'TASK2': '''#!/usr/bin/env python
#... actual code for task2 goes here ...
'''}
# driver portion
(opts, args) = parser.parse_args()
if opts.run_all is not None:
   for task in opts.run_all.split(","):
      task_path = '/tmp/taskfile_%s' % task
      with open(task_path, 'w') as task_file:
         task_file.write(TASK_CODE[task])
      # note: should probably do better error handling.
      distribute_cmd(task_path)
于 2012-10-20T17:39:20.240 に答える