15
$\begingroup$

I don't want to use /Application.../blender -P my_script.py but I want to tell a running Blender process to execute a script.

Is there an existing method to tell a running Blender process to execute a python script?

For example using http://localhost:123/run_script=myscript.py

$\endgroup$
1
  • 1
    $\begingroup$ I would like to create a vim shortcut, that's why I'm asking. $\endgroup$
    – mipmip
    Nov 13, 2015 at 15:44

3 Answers 3

18
$\begingroup$

This can be done with sockets, using the following examples you can run from the command line:

From the first terminal:

blender --python blender_server.py

From a second terminal:

python blender_client.py /path/to/myscript.py

This will execute /path/to/myscript.py in the first Blender instance.

You can send multiple scripts or run the client multiple times.

Note that this is a simple example, to get return codes in the client or make the port configurable... etc, this would have to be extended.

It could even be made to sent the entire script, or compressed Python byte-code over a network, none of this is especially hard. It just depends what you're after.


blender_server.py

# Script to run from blender:
#   blender --python blender_server.py

PORT = 8081
HOST = "localhost"
PATH_MAX = 4096


def execfile(filepath):
    import os
    global_namespace = {
        "__file__": filepath,
        "__name__": "__main__",
    }
    with open(filepath, 'rb') as file:
        exec(compile(file.read(), filepath, 'exec'), global_namespace)


def main():
    import socket

    serversocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    serversocket.bind((HOST, PORT))
    serversocket.listen(1)

    print("Listening on %s:%s" % (HOST, PORT))
    while True:
        connection, address = serversocket.accept()
        buf = connection.recv(PATH_MAX)

        for filepath in buf.split(b'\x00'):
            if filepath:
                print("Executing:", filepath)
                try:
                    execfile(filepath)
                except:
                    import traceback
                    traceback.print_exc()


if __name__ == "__main__":
    main()

blender_client.py

#!/usr/bin/env python
# Script to send paths to run in blender:
#   blender_client.py script1.py script2.py

PORT = 8081
HOST = "localhost"

def main():
    import sys
    import socket

    clientsocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    clientsocket.connect((HOST, PORT))

    for arg in sys.argv[1:]:
        clientsocket.sendall(arg.encode("utf-8") + b'\x00')


if __name__ == "__main__":
    main()
$\endgroup$
6
  • $\begingroup$ For me this freezes Blender until I press Ctrl + C to stop the server $\endgroup$ Aug 10, 2021 at 21:59
  • $\begingroup$ Right, you could use a timer to check for events if you wanted. $\endgroup$
    – ideasman42
    Aug 10, 2021 at 23:11
  • $\begingroup$ blender --python blender_server.py opens blender as blank (grey window, not even splash screen). Any ideas? $\endgroup$
    – jjk
    May 22, 2022 at 13:13
  • $\begingroup$ @jjk right, if you want to run it from some other context you could use a timer for example. $\endgroup$
    – ideasman42
    May 22, 2022 at 23:23
  • $\begingroup$ @ideasman42 I'll rephrase: What's the purpose of blender_server.py as posted (freezing blender)? $\endgroup$
    – jjk
    May 23, 2022 at 7:59
3
$\begingroup$

I think this is a simple solution and avoids dependencies entirely.

https://github.com/zeffii/bpy_externall

Blender (Server)

Here's a small modal operator addon that works like this:

enter image description here

  • Adds a panel to the TextEditor, with a start / end button
  • when Start is pressed it
    • reads a file located at /path/whatever.io every n seconds.
      • If the file is empty we do nothing,
      • If the file contains a filepath (for instance to a python file) then the filepath is executed with Blender's python (as if it was running from the TextEditor). Once completed the operator will erase the contents of the file to indicate that it executed the path.
    • When End is pressed the modal operator stops reading that file location.

External Text Editor (Client)

The add-on includes an example of a SublimeText3 plugin that acts as a Client. All this 'Sender' plugin needs to do is write the filepath of the python file you want Blender to execute to /path/whatever.io

$\endgroup$
5
  • $\begingroup$ Wow this looks great! $\endgroup$
    – mipmip
    Nov 16, 2015 at 11:28
  • 1
    $\begingroup$ This concept is fine! I've created a small pull-request. I'll start working on a vim-plugin rightaway. $\endgroup$
    – mipmip
    Nov 16, 2015 at 16:17
  • 1
    $\begingroup$ First vim plugin version is here $\endgroup$
    – mipmip
    Nov 16, 2015 at 21:30
  • $\begingroup$ I don't have a windows machine, but it should not be to hard to create working version for window too. I presume there are a lot of Blender users running Windows. $\endgroup$
    – mipmip
    Nov 16, 2015 at 21:41
  • $\begingroup$ ideasman42's answer using sockets is really cool, i'll need to study it :) $\endgroup$
    – zeffii
    Nov 16, 2015 at 21:43
3
$\begingroup$

I did ask a similar question, but as this one is way more popular so I guess that answer should be here. Question on command port

This usually is done with command port that listens for commands, but there's apparently no such thing in Blender. I've created an addon that implements this functionality. It can be found on github:

$\endgroup$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .