みなさんこんにちは。今年度も、もう終わってしまいますね。3年間続いたコロナ禍も、もう何となくウヤムヤにしてしまおうという雰囲気が漂いつつあり、最近は人の行き来が活発になってきているようです。かく言う私も徐々に、今まで会っていなかった人たちとの交流を再開しつつあります。基本が引きこもり体質なので外出しないならしないで特に気にならない私ですが、それでも久しぶりに人に会うのは大きな刺激になります。とは言ってもマスクの規制が緩和されて1週間で即座にインフルエンザが流行り出すなど気を抜くことができない状態なのは少しも変わらないので、皆さんご注意ください。

記事の目次

    システムとしてくみあげる

    前回までで、アプリケーション起動用のBATファイルを作成して、その中でローカルマシンにvenvをつくってプロジェクト用の環境を自動的にセットアップできるようにしました。これでも十分便利なしくみになっていますが、アプリケーションやプロジェクトごとに個別にBATファイルを用意して、その中で共通の処理を用意することになります。また、ルール変更などで処理内容を変更する必要が出てきたときに、全てのBATを更新しなければいけません。これではすぐに破綻してしまうので、きちんとシステム化をしましょう。

    管理を階層化する

    管理すべき内容はその範囲ごとに階層化できます。例として、以下の3つに分けることができます。

    [アプリケーションごとのルール]
    [プロジェクトごとのルール]
    [会社全体のルール]

    下から上に向かって細分化していて、下のルールは上の階層でも共有することになります。現在制定しているルールを当てはめてみると、以下のように分かれます。

    [アプリケーションごとのルール]
    - 特になし

    [プロジェクトごとのルール]
    -使用するMayaのバージョンは2023

    [会社全体のルール]
    -実行ファイルやパッケージはファイルサーバ上に置く
    -C:\PJ\(プロジェクト名)以下にvenvを置く
    -ツール類の置き場はT:にマウントする
    -T:\Toolsに実行ファイル類を置く
    -T:\PJ\(プロジェクト名)以下にプロジェクト関連の設定を置く
    -T:\wheelhouseにパッケージ類を置く
    -プロジェクトデータはP:にマウントする
    -Mayaの使用ルール

    簡易的なルール決めなので、アプリケーションごとのルールは特に決めていないです。「使用するMayaのバージョン」というのはプロジェクトごとに決められるものです。ただ、会社全体に共通する「Mayaの使用ルール」というのもあるので、これは分けて管理した方が良さそうです。それ以外のルールは会社全体のものとして全てのプロジェクトで共有されるものですね。

    ランチャーをつくる

    この分類に従って処理内容を整理し、アプリケーションランチャーを作成します。基になるのは前回作成したBATです。


    @echo off
    
    REMプロジェクト固有の設定
    set PJNAME=launcherTest
    set ENVNAME=venvMaya2023
    
    REMシステム共通の設定
    set TOOLS_BASE=T:
    set VENV_BASE=C:
    
    
    REM設定から決まる各種変数
    set VENV_PATH=%VENV_BASE%\PJ\%PJNAME%\%ENVNAME%
    set VENV_PYTHON=%VENV_PATH%\Scripts\python.exe
    set WHEELHOUSE=%TOOLS_BASE%\wheelhouse
    
    
    REMローカル環境にプロジェクト用フォルダをつくる
    mkdir %VENV_BASE%\PJ\%PJNAME%
    
    REMローカル環境にvenvをつくる
    %TOOLS_BASE%\Tools\python-3.9.7\python -m venv %VENV_PATH%
    %VENV_PYTHON% -m pip install --upgrade pip
    
    REM venvにパッケージをインストールする
    %VENV_PYTHON% -m pip install -r %~dp0%ENVNAME%.txt --find-links %WHEELHOUSE%
    
    REM venvを有効にしてMayaを起動する
    set MAYA_UI_LANGUAGE=en_US
    set PYTHONPATH=%VENV_PATH%\Lib\site-packages
    
    "C:\Program Files\Autodesk\Maya2023\bin\maya.exe"

    これを整理します。まず、必要なパラメータを設定ファイルとして書き出します。


    T:\Tools\launcher.jsonに会社全体のルールを記述しておきます。


    {
      "tools_base": "T:\\",
      "venv_base": "C:\\",
      "wheelhouse": "T:\\wheelhouse"
    }

    T:\PJ\(プロジェクト名)\config.jsonにプロジェクト全体ルールを記述しておきます。


    {
      "name": "launcherTest"
    }

    T:\PJ\(プロジェクト名)\maya.json にアプリケーションに関係するルールを記述しておきます。


    {
      "maya_ver": "2023",
      "venv_name": "venvMaya2023"
    }

    アプリケーションランチャーを作成します。


    import os
    import sys
    import subprocess
    import json
    
    
    def maya(global_conf, pj_conf, app_conf):
      maya_exe = os.path.join(r'C:\Program Files\Autodesk\Maya%s\bin\maya.exe' % app_conf['maya_ver'])
    
      env = {}
      env.update(os.environ)
      env['tools_base'] = global_conf['tools_base']
      env['venv_base'] = global_conf['venv_base']
      env['pj_name'] = pj_conf['name']
          
      subprocess.Popen(maya_exe, env=env)
    
    
    def prepare_venv(tools_py, wheelhouse, venv_base, pj_name, name, requirements_txt):
      pj_path = os.path.join(venv_base, 'PJ', pj_name)
      venv_path = os.path.join(pj_path, name)
      venv_python = os.path.join(venv_path, 'Scripts', 'python.exe')
    
      if not os.path.exists(pj_path):
        os.makedirs(pj_path)
    
      cmd = [
        tools_py ,
        '-m',
        'venv',
        venv_path
      ]
      p = subprocess.Popen(cmd)
      p.wait()
    
      cmd = [
        venv_python,
        '-m',
        'pip',
        'install',
        '--upgrade',
        'pip'
      ]
      p = subprocess.Popen(cmd)
      p.wait()
    
      cmd = [
        venv_python,
        '-m',
        'pip',
        'install',
        '-r',
        requirements_txt,
        '--find-links',
        wheelhouse
      ]
      p = subprocess.Popen(cmd)
      p.wait()
    
    
    def launcher(pj_name, app_name):
      global_conf_json = os.path.join(os.path.dirname(__file__), 'launcher.json')
      fp = open(global_conf_json, 'r')
      global_conf = json.load(fp)
      fp.close()
    
      pj_conf_json = os.path.join(global_conf['tools_base'], 'PJ', pj_name, 'config.json')
      fp = open(pj_conf_json, 'r')
      pj_conf = json.load(fp)
      fp.close()
    
      app_conf_json = os.path.join(global_conf['tools_base'], 'PJ', pj_name, '%s.json' % app_name)
      fp = open(app_conf_json, 'r')
      app_conf = json.load(fp)
      fp.close()
    
    
      requirements_txt = os.path.join(global_conf['tools_base'], 'PJ', pj_name, '%s.txt' % app_conf['venv_name'])
      prepare_venv(sys.executable, global_conf['wheelhouse'], global_conf['venv_base'], pj_name, app_conf['venv_name'], requirements_txt)
    
    
      if app_name == 'maya':
        maya(global_conf, pj_conf, app_conf)
    
      return True
    
    
    if __name__ == '__main__':
      pj_name = sys.argv[1]
      app_name = sys.argv[2]
    
      launcher(pj_name, app_name)

    ランチャーを起動するためのBATを用意します。


    @echo off
    
    set PY_EXE=%~dp0python-3.9.7\python.exe
    
    set PY=%~dp0launcher.py
    %PY_EXE%  %PY% %1 %2

    最後に、BATを起動するためのショートカットをT:\PJ\launcherTest\Mayaに作成しておきます。


    これで、このショートカットを実行するだけで、venvの準備などを自動で行なった後にMayaが立ち上がるようになります。


    まとめ

    これまで積み上げてきた要素技術を組み上げて、遂にアプリケーションランチャーの作成まで辿り着くことができました。しかもユーザーから見れば、いつものようにMayaを立ち上げるためにMayaアイコンを実行するだけで良いので、venvやパッケージ管理といったことをまったく意識する必要がありません。ここまで隠されてしまうと、周囲からは「何だかアイツは時間をかけて仕事をしているのに、何も成果が上がってないじゃないか!!プンプン!!」と言われてしまいかねません。笑。技術者としては非常に誇らしいことなのですが、社会人としては存亡の危機なのでアピールも忘れないようにしましょう!!


    第53回の公開は、2023年4月を予定しております。





    痴山紘史

    日本CGサービス(JCGS) 代表

    大学卒業後、株式会社IMAGICA入社。放送局向けリアルタイムCGシステムの構築・運用に携わる。その後、株式会社リンクス・デジワークスにて映画・ゲームなどの映像制作に携わる。2010年独立、現職。映像制作プロダクション向けのパイプラインの開発と提供を行なっている。新人パパ。娘かわいい。





    TEXT_痴山紘史 / Hiroshi Chiyama(日本CGサービス
    EDIT_尾形美幸 / Miyuki Ogata(CGWORLD)、中川裕介/ Yusuke Nakagawa(CGWORLD)