2023-05-05

hdefereval

以下の Python スクリプトを丸ごとペーストして Python Source Editor で実行すると問題なく実行できるが、Python Shell で実行するとフリースするかクラッシュする。この問題の原因と対処を紹介する。

from PySide2.QtCore import QUrl
from PySide2.QtWidgets import QMainWindow
from PySide2.QtWebEngineWidgets import QWebEngineView

import os
import sys

class MainWindow(QMainWindow):
    def __init__(self, *args, **kwargs):
        super(MainWindow, self).__init__(*args, **kwargs)

        self.browser = QWebEngineView()
        self.setCentralWidget(self.browser)
window = MainWindow()
window.show()

使用したビルド:

  • Houdini 19.5.534/569 (Py3.9)

Python Shell

上のスクリプトを Python Shell にそのままペーストし、Enter キーで実行すると、エラーが出てクラッシュするか、エラーなしでフリーズするなど、好ましくない結果になる。

Python Source Editor

上のスクリプトを Python Source Editor の上段にペーストして Apply ボタンをクリックすると、まっさらなウィンドウが現れる。クラッシュもせず、エラーも現れない。

原因と解決策

Python Shell からの実行時にクラッシュ・フリーズの原因となっているのは、PySide2/Qt が、その仕様上、 Houdini のメインスレッド上で実行されなければならないから。スクリプトを Houdini のメインスレッドで実行するには hdefereval という関数を使い、以下のように書き換える。

import hdefereval

def showMainWindow():
    from PySide2.QtCore import QUrl
    from PySide2.QtWidgets import QMainWindow
    from PySide2.QtWebEngineWidgets import QWebEngineView


    import os
    import sys


    class MainWindow(QMainWindow):
        def __init__(self, *args, **kwargs):
            super(MainWindow, self).__init__(*args, **kwargs)


            self.browser = QWebEngineView()
            self.setCentralWidget(self.browser)


    window = MainWindow()
    window.show()


    # Assign the new window object to a persistent attribute in the hou.session module to keep the window alive.
    hou.session.window = window


hdefereval.executeDeferred(showMainWindow)

このスクリプトであれば、Python Source Editor にペーストして Apply を押しても、例えば、このファイルを C:/tmp/open_window.py として配置し、Python Shell で以下のように実行してもウィンドウが作成できる。
with open("C:/tmp/open_window.py","r") as f:
    exec(f.read())
なお、hdefereval の詳細は $HHP/hdefereval.py にある。

0 件のコメント:

コメントを投稿