0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

DCCツールで頻出する前後処理をコンテキストマネージャで再利用可能にする

Posted at

環境

  • Windows
  • Autodesk Maya 2025.3

前処理、後処理の再利用

DCCツールで前処理・後処理をパターン化して再利用できるようにするためには、with文に渡すためのコンテキストマネージャを作成すると便利です。

コンテキストマネージャの作成について

コンテキストマネージャ型

コンテキストマネージャは __enter__ メソッドと __exit__ メソッドを持つクラスを定義することで作成可能です。

class SampleContext:
    def __init__(self, s):
        self._s = s

    def __enter__(self):
        print("enter")
        return self._s  # as キーワードで参照できる

    def __exit__(self, exc_type, exc_val, exc_tb):
        print("exit")


def sample(s):
    with SampleContext(s) as f:
        print(f)

with文実行時には下記の順番で実行されます。

  1. __enter__ メソッドの処理
  2. withブロック内の処理
  3. __exit__ メソッドの処理
出力結果
>>> sample("sample")
enter
sample
exit

@contextlib.contextmanager

標準ライブラリにある @contextlib.contextmanager デコレータを使用すると簡潔に定義できます。

from contextlib import contextmanager


@contextmanager
def sample_context(s):
    print("enter")
    try:
        yield s  # as キーワードで参照できる
    finally:
        print("exit")


def sample(s):
    with sample_context(s) as f:
        print(f)

yield文より前に書かれたコードが前処理として、yield文より後に書かれたコートが後処理として実行されます。

出力結果
>>> sample("sample")
enter
sample
exit

@contextlib.contextmanager で作成するその他のメリットとしてデコレータとしての利用も可能な点が挙げられます。

from contextlib import contextmanager


@contextmanager
def sample_context():
    print("enter")
    try:
        yield
    finally:
        print("exit")


@sample_context()
def sample_deco():
    print("sample_deco")
出力結果
>>> sample_deco()
enter
sample_deco
exit

似たようなものとしてクラスベースのコンテキストマネージャをデコレータとして使用できるようにする基底クラス ContextDecorator などもあります。

Maya での利用例

DCCツールでの利用例として、Mayaの例を下記に記載します。

mayapy での初期化

バッチ処理での利用例です。

from contextlib import contextmanager
import maya.standalone


@contextmanager
def mayapy_initialize():
    maya.standalone.initialize()
    try:
        yield
    finally:
        maya.standalone.uninitialize()
利用例
if __name__ == "__main__":
    import maya.cmds as cmds

    with mayapy_initialize():
        print(cmds.polyCube())

undo/redo

Qt for Python で実装したGUIのコールバック関数にデコレートする例です。

from contextlib import contextmanager

from maya import cmds


@contextmanager
def undoredo():
    cmds.undoInfo(ock=True)
    cmds.refresh(su=True)
    try:
        yield
    finally:
        cmds.refresh(su=False)
        cmds.undoInfo(cck=True)
利用例
from PySide6 import QtWidgets

from maya import cmds
from maya.app.general.mayaMixin import MayaQWidgetBaseMixin


class Window(MayaQWidgetBaseMixin, QtWidgets.QMainWindow):
    def __init__(self):
        super().__init__()

        widget = QtWidgets.QWidget()
        self.setCentralWidget(widget)

        layout = QtWidgets.QVBoxLayout()
        widget.setLayout(layout)

        self._button = QtWidgets.QPushButton("Apply")
        self._button.clicked.connect(self._button_clicked)
        layout.addWidget(self._button)

    @undoredo()
    def _button_clicked(self, *args):
        cmds.polySphere()
        cmds.polyCube()
        cmds.polyCylinder()

参考

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?