For a slightly 'hacky' way of achieving this, create a handler to look for the presence of a file and execute the contents of the file (and remove the file) whenever it is found. Once the handler is running all that is required is for any script to be executed to be copied into a specific location and Blender will 'consume' it.
In a text editor, click 'new' and paste the following code (and name it 'exec_from_file.py') :
import bpy
import os
filename = 'blender_script.run'
def scan_for_file_to_exec(scn):
global filename
try:
file = open(filename)
except FileNotFoundError:
pass
else:
print("scan_for_file_to_exec: Got file")
content = file.read()
file.close()
os.remove(filename)
exec(content)
bpy.app.handlers.scene_update_pre.append(scan_for_file_to_exec)
print("scan_for_file_to_exec: Scanning for file '%s' in directory '%s'" % (filename, os.getcwd()))
Click 'Run Script' and optionally tick the 'Register' checkbox to automatically run the script whenever the blend file is opened. This will install a handler that will be triggered every time the scene is updated (which appears to occur continuously). The script outputs a line to the console window when it first runs, indicating the file and directory it is scanning for.
scan_for_file_to_exec: Scanning for file 'blender_script.run' in directory '/home/rich'
Whenever the file exists blender will read the contents, remove the file, and execute the code.
All that is now required outside of Blender to trigger the running of a script is to copy the required script into the relevant location and it should immediately disappear and be executed.
For Linux :
cp my_script.py /home/rich/blender_script.run
For Windows :
copy my_script.py c:/users/rich/blender_script.run
For multiple files, copy each file in place, waiting for each to be consumed before copying the next.
NOTE : You need to ensure that Blender is invoked from a location where your user has permissions to read/write files - or you need to run 'As Administrator'.
For example, once the above handler is running (and assuming both you and Blender have permission to read/write to the relevant directory) you can create Suzanne by running the following from the command line (in the relevant directory) :
echo bpy.ops.mesh.primitive_monkey_add(radius=2) >blender_script.run
Then create another different sized in a different location :
echo bpy.ops.mesh.primitive_monkey_add(radius=2, location=(-1,-1,-3)) >blender_script.run
An alternative method is to use a similar handler to read the input from the 'blender' process itself and execute any commands received on that stream. When you launch Blender you can direct the output of another process (eg, a python script) into the 'blender' process and Blender will execute them as they are received.
For this, create the following script in a Text Editor block named 'exec_from_stdin.py' and click Run Script. Don't forget to click 'Register' so that it runs automatically when the blend file is loaded.
import bpy
import select
import sys
def my_scene_handler(scn):
#print("In scene handler")
# Check to see if any input on STDIN
if select.select([sys.stdin,],[],[],0.0)[0]:
# Read a line from input
line = sys.stdin.readline()
print("Got a line '%s'" % line)
exec(line)
bpy.app.handlers.scene_update_post.append(my_scene_handler)
Now when you launch Blender to load the file it will listen for commands on 'stdin' (standard input).
You can now 'pipe' any input into Blender by launching it using a command similar to the following :
<command> | blender
NOTE : This method doesn't appear to work correctly under MS Window - Linux (and, presumably Mac) only - due to differences in how Windows handles input streams.