multiprocessing.forking prepareメソッドで落ちる..

めも。
Mayaからプロセス起動できない時のデバッグトレースのログ。

先に結論から書くと、prepareメソッドでimp.load_module 呼び出しをする際にmayaから起動した場合、’import maya’を実施してしまい、ImportError: ‘No module named maya’で終わってしまう。(これは、get_preparation_dataメソッドで d[‘main_path’]に mayaのフルパスが渡される為に起こる。)

とりあえず動かすようにするには、set_executable(exe_path, pyfile_path)とかで呼び出せるようにする仕掛けが必要になりそう。(set_executableについては別記事を参照のこと。)
実際に、set_executable, get_preparation_dataメソッド辺りを書き換えたものを参照するようにしてみると動作を確認できた。

ただ標準添付のモジュールを弄ることになるので、PYTHONPATHに最優先でカスタムのmultiprocessingモジュールを参照するような対応をして、標準添付のモジュールを変更しないような対応が必要。

補足。
multiprocessingモジュールにはいろいろなプロセス起動方法があるけど、試したのはstart~joinで行う単純なプロセス起動のみ。
Pool使ったりしている場合は他にも対策が必要みたいで、前述の対策だけではプロセスが生きたままになってしまった。
単に、poolをclose&joinし忘れていただけだった。

うまく動く場合(CPythonでファイル指定した)はこんなログに。

その後

 頭いい人が、こうすりゃいいんだよって記事書いてたのをたまたま(自分のページに行こうとしたらタイプミスで検索になっちゃって)見つけちゃったので、めも。
 こうやって使うものだったのね…ナルホド勉強になります。

[Python] sys.executable

実行用プロセスのファイルパスを得る手段が用意されていたので、めも。

MayaからPythonスクリプトを実行している場合、「maya.exe」のパスが得られる。
当然だったのだけど、出来たら「mayapy.exe」になっていて欲しかった…

Mayaから子プロセスでPythonスクリプトを実行する時は、こんな流れで呼び出してやらないとMayaが二重起動してガッカリな羽目になりますので要注意です。

そういえば、

 こんな記事を見つけた。
 いっその事CPythonのパスを環境変数設定で先にしつつ、python.exeをコピーしてmaya.exeにしといたら、勝手にCPython起動してくれるのかしら?
 そんなハック、宜しくない行為だとは思いますががが…

 試しにやってみたけど、別にそんな動きしなかった…どういう事だか判らんです。

multiprocessing

 multiprocessingモジュールには、set_executableというメソッドがあった。
 これを使うと、プロセスを起動する際のPythonの系を変えることが出来る。

 しかし、maya.exe組み込みのPythonからはうまく動作させることが出来なかった。
 CPythonやmayapyからは動くのだが、標準入出力の兼ね合いなのか?原因が分からない。非常に残念…
 問題判明。(⇒関連記事を参照のこと。)

[Python] asyncioモジュール

 ブロッキングI/O向けの非同期処理モジュール。
 スレッドやプロセスで処理停滞を回避するなら、第3の選択肢としてasyncioを覚えるのが吉です。

 asyncとは、asynchronous(非同期)という意味です。
 asyncioは、「非同期なI/O制御」みたいな意味かと(たぶん)

 MayaとかPython2.7なので標準では使えませんが、trolliusというバックポートのモジュールがあるので、ちょっとしたコードの修正でasyncio互換の動作が得られます。
 「pip install trollius」でインストール処理が行われますが、必要に応じてコンパイラが必要になります。
 その場合、前記事のVC++Python2.7をインストールしておくと幸せになれます。(VC++持ってる場合は、入れなくてもOKだとは思いますけど)

asyncioとは?

 Python3.4あたりから標準添付されている、非同期処理モジュール。
 asyncio以前から存在したFutureオブジェクトの機能を、非同期制御用に独立させた感じ。

 みどころの機能は、以下の通り。
 ・イベントループで、登録した処理を登録順に実行してくれる。
 ・上記の機能を利用して、同期処理関数(ブロッキング関数)について終了したものから順次処理してくれる。
 ・単なるイベントループでも、「指定した秒数後に起動する」といった指定ができる。(2秒間隔で…など、間欠的に処理を起動させることにも使える。)

 非同期処理を謳っているだけに、「ブロッキング関数を終わったものから順次処理する」というのがキモの部分。
 そうでなくても、単純なタスクシステムのような動作を得られるし、そのままイベントループとして使うこともできる。

 わざわざ実装しなくても、こうしたイベントループを使えるのは素晴らしい。

 以下は、exampleのHello,World!(…に、stop呼び出しを付け加えたもの。ほっとくと永遠に唱え続けるので。)