如何使用 shotgunEvent 进程加载不同的 Toolkit 核心模块?

非常感谢 Benoit Leveau (Milk VFX) 分享此信息。

问题

如果您使用的是 shotgunEvents 进程,您可能需要在特定事件对应的插件内部执行 Toolkit 操作。这并非易事,因为 Python 仅导入一次模块。因此,如果您在第一次运行该插件时导入了用于项目 A 的 Toolkit 核心 API,则在此进程的使用周期内将始终导入该版本。这意味着,如果分派给该插件的下一个事件用于项目 B,则当您尝试使用来自项目 A 的核心 API 实例化用于项目 B 的新 Toolkit 对象时,可能会发生错误。

由于 Toolkit 是以项目为中心,每个项目将会具有不同版本的 Toolkit 核心和配置。为了创建正确的 Toolkit 实例,您可能需要从其他位置导入不同版本的 sgtk 模块,具体取决于生成了该事件的项目。如前所述,默认情况下 Python 仅导入一次模块。 因此,即使您将 sys.path 修改为指向 sgtk 模块的新位置并尝试进行导入,Python 也会发现它已经导入了一个 sgtk 模块而不会进行替换。之后,当您尝试执行 Toolkit 操作的项目不同于加载核心 API 所用的项目时,将会引发错误。

示例:

  • 事件 123 用于项目 A
  • 用于项目 A 的核心 API 位于 /mnt/toolkit/projectA/install/core/python
  • 在 sys.path 前面加上此目录
  • “import sgtk”从该位置进行导入
  • 使用此核心 API 实例化一个 Toolkit 实例并执行一些操作
  • 将核心 API 目录从 sys.path 中去掉
  • 事件 234 用于项目 B
  • 用于项目 B 的核心 API 位于 /mnt/toolkit/projectB/install/core/python
  • 在 sys.path 前面加上此目录
  • “import sgtk”不会执行任何操作,因为 Python 发现它已经导入了 sgtk
  • 使用此核心 API 实例化一个 Toolkit 实例并执行一些操作
  • 这将导致错误,因为 Toolkit 核心用于项目 (A),而不是您尝试执行操作的项目 (B)。

 

解决方法

大体上说,下面的示例说明了在可能已经导入不同版本模块的情况下,如何在脚本或插件中导入正确版本的 sgtk 核心。 原始导入将会卸载并从 Python 内存中移除,这样,便可成功导入并使用新的模块实例。

"""
Example of how to import the correct sgtk core code in a script where
a different instance of the module may have already been imported. The
original import is unloaded and removed from memory in Python so the new
instance of the module can be imported and used successfully.
    
Thanks to Benoit Leveau @ Milk VFX for sharing this.
"""

import os
import sys


def import_sgtk(project):
    """
    Import and return the sgtk module related to a Project.
    This will check where the Core API is located on disk (in case it's localized or shared).
    It shouldn't be used to get several instances of the sgtk module at different places.
    This should be seen as a kind of 'reload(sgtk)' command.

:param project: (str) project name on disk for to import the Toolkit Core API for. """ # where all our pipeline configurations are located shotgun_base = os.getenv("SHOTGUN_BASE", "/mnt/sgtk/configs") # delete existing core modules in the environment for mod in filter(lambda mod: mod.startswith("tank") or mod.startswith("sgtk"), sys.modules): sys.modules.pop(mod) del mod # check which location to use to import the core python_subfolder = os.path.join("install", "core", "python") is_core_localized = os.path.exists(os.path.join(shotgun_base, project, "install", "core", "_core_upgrader.py")) if is_core_localized: # the core API is located inside the configuration core_python_path = os.path.join(shotgun_base, project, python_subfolder) else: # the core API can still be localized through the share_core/attach_to_core commands # so look in the core_Linux.cfg file which will give us the proper location (modify this # to match your primary platform) core_cfg = os.path.join(shotgun_base, project, "install", "core", "core_Linux.cfg") if os.path.exists(core_cfg): core_python_path = os.path.join(open(core_cfg).read(), python_subfolder) else: # use the studio default one # this assumes you have a shared studio core installed. # See https://support.shotgunsoftware.com/entries/96141707 core_python_path = os.path.join(shotgun_base, "studio", python_subfolder) # tweak sys.path to add the core API to the beginning so it will be picked up if sys.path[0] != "": sys.path.pop(0) sys.path = [core_python_path] + sys.path

# Remove the TANK_CURRENT_PC env variable so that it can be populated by the new import
del os.environ["TANK_CURRENT_PC"] # now import the sgtk module, it should be found at the 'core_python_path' location above import sgtk return sgtk

 

关注

0 评论

登录写评论。