Source code for blendersynth.run.run_this_script

"""Quick utility to run the current script from Blender"""
import subprocess
import inspect
import sys
import os
from ..utils.blender_setup.blender_locator import get_blender_path
from ..file.tempfiles import create_temp_file, cleanup_temp_files as cleanup
from shutil import copyfile


def _copy_over_script(filepath: str) -> str:
    """Copies over a python script to a tempfile, returning the path.
    Removes certain lines so it can run in blender"""
    remove_lines_containing = [".run_this_script"]
    new_lines = []
    with open(filepath, "r") as f:
        lines = f.readlines()
        for line in lines:
            if not any([s in line for s in remove_lines_containing]):
                new_lines.append(line)

    new_filepath = create_temp_file(ext=".py")
    with open(new_filepath, "w") as f:
        f.writelines(new_lines)

    return new_filepath


[docs] def is_blender_running(): """Returns True if blender is running, False otherwise""" try: import bpy return bpy.__file__ is not None except: return False
[docs] def run_this_script( *args, open_blender: bool = False, debug: bool = False, IDE: str = "PyCharm", port: int = 5678, host: str = "localhost", blend_src: str = None, blend_as_copy: bool = False, **kwargs, ): """Run the script in which this function is called from Blender. :param open_blender: If True, open a Blender instance after all code is executed, otherwise run in background :param debug: If True, will run in debug mode :param IDE: IDE to use for debugging. Currently only PyCharm and VSCode are supported :param port: Port to use for debugging :param host: Host to use for debugging :param blend_src: Path to blend file to open (note: this is preferable to `blendersynth.load_blend` as it handles context better) :param blend_as_copy: If True, will copy `blend_src` to a temp file before opening - this is useful if you want to make sure you don't accidentally override your `blend_src` file args & kwargs are passed to the script being run as command line arguments. The flag `--run_this_script` is passed to the script being run to indicate that it is being run from `run_this_script`. Use function `is_from_run_this_script` to check if the script is being run from `run_this_script`. """ running_in_blender = is_blender_running() caller_path = inspect.stack()[ 1 ].filename # path of script that called this function if not running_in_blender: # if blender is not running this script caller_dir = os.path.dirname(caller_path) env = os.environ.copy() env["PYTHONPATH"] = caller_dir + os.pathsep + env.get("PYTHONPATH", "") blender_path = get_blender_path() if blend_src is not None and blend_as_copy: new_filepath = create_temp_file(ext=".blend") copyfile(blend_src, new_filepath) blend_src = new_filepath commands = ( [blender_path] + [blend_src] * (blend_src is not None) + ["--background"] * (not open_blender) + ["--python", caller_path, "--"] ) for arg in args: commands += [f"--{arg}"] for key, value in kwargs.items(): commands += [f"--{key}", str(value)] commands += ['--run_this_script'] # flag to indicate that this is being run from run_this_script subprocess.call(commands, env=env) cleanup() # cleanup temp files sys.exit() # exit the script once blender is finished else: if debug: IDE = IDE.lower() assert IDE in [ "pycharm", "vscode", ], f"IDE `{IDE}` not supported, only PyCharm and VSCode are supported" if IDE == "pycharm": import pydevd_pycharm pydevd_pycharm.settrace( host, port=port, stdoutToServer=True, stderrToServer=True, suspend=False, ) elif IDE == "vscode": import debugpy debugpy.listen((host, port)) debugpy.wait_for_client() # blender is running this script if open_blender: # load the script into blender for viewing import bpy
# REMOVED FUNCTIONALITY TO LOAD SCRIPT TEXT INTO BLENDER AS CAUSING ISSUES # from ..utils import layout # caller_path = bpy.path.abspath(caller_path) # script_path = _copy_over_script(caller_path) # text_block = bpy.data.texts.load(script_path) # layout.change_area_to("DOPESHEET_EDITOR", "TEXT_EDITOR") # layout.get_area("TEXT_EDITOR").spaces[0].text = text_block
[docs] def is_from_run_this_script(): """Returns True if this script is being run from run_this_script""" return '--run_this_script' in sys.argv