Created
January 16, 2025 10:45
-
-
Save tin2tin/d4b55d0ca0bffad86ef053db31f5db06 to your computer and use it in GitHub Desktop.
Threading
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import bpy | |
import subprocess | |
import threading | |
import re | |
# Function to parse progress from subprocess output | |
def parse_progress(line): | |
""" | |
Parses progress information from a line of output. | |
Example format: '23/100 [===> ] 23%' or similar. | |
Adjust regex as needed for your specific progress format. | |
""" | |
match = re.search(r"(\d+)/(\d+)", line) | |
if match: | |
current = int(match.group(1)) | |
total = int(match.group(2)) | |
progress = current / total | |
return progress | |
return None | |
# Function to handle subprocess output | |
def process_output(stdout, stderr): | |
""" | |
Reads the subprocess output and updates Blender's system bar progress. | |
""" | |
wm = bpy.context.window_manager | |
wm.progress_begin(0, 1) # Start progress (min=0, max=1) | |
try: | |
for line in iter(stdout.readline, b""): | |
line = line.decode().strip() | |
print(line) # Print to Blender's console for debugging | |
# Try to parse progress from the line | |
progress = parse_progress(line) | |
if progress is not None: | |
wm.progress_update(progress) # Update Blender progress bar | |
# Process stderr if needed | |
if stderr: | |
for line in iter(stderr.readline, b""): | |
print("Error:", line.decode().strip()) | |
finally: | |
wm.progress_end() # End progress | |
# Function to run any subprocess command in a thread | |
def run_subprocess_in_thread(command, **kwargs): | |
""" | |
Run a subprocess command in a separate thread. | |
Args: | |
command (list or str): The command to run (list for arguments). | |
**kwargs: Additional keyword arguments to pass to subprocess.Popen. | |
""" | |
def task(): | |
# Run the subprocess | |
try: | |
process = subprocess.Popen( | |
command, | |
stdout=subprocess.PIPE, | |
stderr=subprocess.PIPE, | |
text=True, # Ensure text output (Python 3.6+) | |
**kwargs, | |
) | |
process_output(process.stdout, process.stderr) | |
except Exception as e: | |
print(f"Subprocess Error: {e}") | |
# Run the task in a separate thread | |
thread = threading.Thread(target=task) | |
thread.start() | |
# Add a button in the UI to trigger the subprocess | |
class RunSubprocessOperator(bpy.types.Operator): | |
"""Run Subprocess Example""" | |
bl_idname = "wm.run_subprocess_example" | |
bl_label = "Run Subprocess Example" | |
def execute(self, context): | |
# Replace with your actual subprocess command | |
# Example: Simulating progress (Linux/macOS: 'seq', Windows: 'for /L') | |
# This command simulates a progress bar-like output | |
run_subprocess_in_thread(["python", "-c", """ | |
import time | |
for i in range(1, 24): | |
print(f'{i}/23 [{"="*i:<23}] {i*100//23}%') | |
time.sleep(0.5) | |
"""]) | |
return {'FINISHED'} | |
# Register the operator and add to the UI | |
def menu_func(self, context): | |
self.layout.operator(RunSubprocessOperator.bl_idname) | |
def register(): | |
bpy.utils.register_class(RunSubprocessOperator) | |
bpy.types.TOPBAR_MT_file.append(menu_func) | |
def unregister(): | |
bpy.utils.unregister_class(RunSubprocessOperator) | |
bpy.types.TOPBAR_MT_file.remove(menu_func) | |
# Enable the script to run in Blender | |
if __name__ == "__main__": | |
register() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment