CustomSchedulerを作る

Pythonスケジューラーを使用して、スケジューラーの挙動を作成できる。
ここでいうスケジューラーとは、ワークアイテム(実行したいコマンド)をハンドリングするもの。
この挙動を確認しつつ、何をどう動かしているかを調査する。

Untitled

まずはシンプルな構成を作る。
Pythonはprintするだけのシンプルなコード。

Untitled

Evaluate Script DuringをCook(Out-Of-Process)にする。

Out-Of-Processにした場合は、Houdiniのプロセスではなく外部のプロセスでPythonが起動され実行される。

Untitled

Temp以下に data/logs/scripts が作成され、これ単体で実行可能なようになっている。

Untitled

Script以下は、pdgのモジュールと、PythonScript。

PDGでは、まずGenerateが実行されてWorkItemが作られる。

そして、スケジューラーは作成されたWorkItemを onSchedule で環境設定などを行い、workitemのJSONなどをTemp以下に生成して実行をする。

onScheduleのコマンドを上から見ていく。

1
2
# Ensure directories exist and serialize the work item
self.createJobDirsAndSerializeWorkItems(work_item)

https://www.sidefx.com/docs/houdini/tops/pdg/Scheduler.html

ここで、TempディレクトリにWorkingディレクトリを作り、work_itemをjsonにシリアライズ。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
{
    "version": 6,
    "workitem": {
        "nodeName": "pythonscript1",
        "batchParentId": -1,
        "cloneTargetId": -1,
        "loopBeginStackIds": [],
        "loopBeginStackNumbers": [],
        "loopBeginStackIters": [],
        "loopBeginStackSizes": [],
        "customDataType": "scriptdata",
        "customData": "IyBFeGVjdXRlcyBhIFB5dGhvbiBzY3JpcHQsIGVpdGhlciBpbiBwcm9jZXNzIG9yIGFzIGEgam9iCiMKIyBUaGUgZm9sbG93aW5nIHZhcmlhYmxlcyBhbmQgZnVuY3Rpb25zIGFyZSBhdmFpbGFibGUgaW4gYm90aCBjYXNlOgojIHdvcmtfaXRlbQojIGdyYXBoCiMgaW50RGF0YSwgZmxvYXREYXRhLCBzdHJEYXRhLAojIGludERhdGFBcnJheSwgZmxvYXREYXRhQXJyYXksIHN0ckRhdGFBcnJheQojCiMgSW4gYWRkaXRpb24gdG8gdGhlIGFib3ZlLCBpbi1wcm9jZXNzIHNjcmlwdHMgY2FuIGFsc28gYWNjZXNzOgojIHNlbGYgICAgICAgICAtIHRoZSBjdXJyZW50IFBERyBub2RlCiMgcGFyZW50X2l0ZW0gIC0gdGhlIHBhcmVudCB3b3JrIGl0ZW0sIGlmIGl0IGV4aXN0cwoKcHJpbnQoImhlbGxvIikK",
        "attributes": {
            "__pdg_commandstring": {
                "type": 2,
                "flag": 9,
                "own": true,
                "concat": false,
                "value": [
                    "\"__PDG_HYTHON__\"   \"__PDG_SCRIPTDIR__/pythonscript.py\" "
                ]
            }
        },
        "id": 2,
        "index": 0,
        "batchIndex": -1,
        "priority": 0,
        "frame": 0,
        "frameStep": 1,
        "hasFrame": false,
        "isPostCook": true,
        "isStatic": true,
        "isNoGenerate": false,
        "isCloneResultData": false,
        "isFrozen": false,
        "state": 3,
        "type": 0,
        "executionType": 0,
        "cookType": 2
    },
    "graph": { "attributes": {} }
}

workingItemの情報が入っている。
実行するスクリプトは customDataに base64でエンコードされた状態で入っている。

1
2
# expand the special __PDG_* tokens in the work item command
item_command = self.expandCommandTokens(work_item.command, work_item)

このcommandは \"PDG_HYTHON\" \"PDG_SCRIPTDIR/pythonscript.py\
これを展開してsubprocessで実行するコマンドにしている。

1
2
3
4
5
6
7
job_env = os.environ.copy()
job_env['PDG_RESULT_SERVER'] = str(self.workItemResultServerAddr())
job_env['PDG_ITEM_NAME'] = str(work_item.name)
job_env['PDG_ITEM_ID'] = str(work_item.id)
job_env['PDG_DIR'] = str(self.workingDir(False))
job_env['PDG_TEMP'] = temp_dir
job_env['PDG_SCRIPTDIR'] = str(self.scriptDir(False))

Subprocessの環境変数を仕込んで

1
2
# run the given command in a shell
returncode = subprocess.call(item_command, shell=True, env=job_env)

そしてそれを実行。

1
2
3
4
# if the return code is non-zero, report it as failed
if returncode == 0:
    return pdg.scheduleResult.CookSucceeded
return pdg.scheduleResult.CookFailed

最後にクックの結果を返している。

onSchedule

WorkItemを実行する準備が整ったときに評価される。

1
"C:/PROGRA~1/SIDEEF~1/HOUDIN~1.544/bin/hython.exe"   "C:/Users/remir/pdgtemp/8084/scripts/pythonscript.py"

item_command は、PythonScriptの場合PythonExecutable で指定したPythonExeで
pythonscript.py を呼び出すようになっている。

Untitled

作ったスケジューラーはPythonスクリプトとしてExportできる。