11
$\begingroup$

Platform = Ubuntu Linux 64 bit, Blender 2.77a

When creating models using bpy-based python scripting, there many times I need to type in the same code in Blender's python console; every time I invoke a new blender session.

For example if something is wrong with objects, I type the following:

for object in bpy.data.object:
    print(object.name + " is at location " + str(object.location)) 

I would like to put this in an xxx.py file I create in a documents folder so when I need to execute it in the Blender python console at each Blender session, all I would need to do is run the .py file ; this will save a lot of repetitive typing.

How do I do this?

Sam

$\endgroup$
1
  • 3
    $\begingroup$ Note, Blender comes with a template to do just this: Text Editor -> Templates -> Python -> Script Stub $\endgroup$
    – ideasman42
    Apr 20, 2016 at 8:55

3 Answers 3

13
$\begingroup$

This is the equivalent to running the script directly, referencing a scripts path from a 2 line text-block.

filename = "/full/path/to/myscript.py"
exec(compile(open(filename).read(), filename, 'exec'))

You might want to reference a script relative to the blend file.

import bpy
filepath = bpy.path.abspath("//myscript.py")
exec(compile(open(filepath).read(), filepath, 'exec'))
$\endgroup$
1
  • $\begingroup$ Thank you so much Smart Gnan Online!! This is a great forum! $\endgroup$ Apr 20, 2016 at 8:28
4
$\begingroup$

Using blender's text editor you can open a script file to read and edit it. The text editor also has a "Run Script" button to easily run the script you are editing.

An open text file can also be run within the python console with

exec(compile(bpy.data.texts['Text'].as_string(), 'textblock', 'exec'))

this has an advantage when debugging as the variables in the script will remain available in the console after it has been run.

Some time back I started using an addon posted on blender artists that adds a menu to the console which lets you run any open text block in blender's python console. You gave me an idea to expand it a bit by adding another menu made from script files in a directory, the addon will now also list the files within a specific directory which will be loaded and run when chosen. You can download the updated addon here.

$\endgroup$
1
  • $\begingroup$ thanks for sharing that Idea! It fills in the gap between developing a full blown operator and just an expression typed into the console. Perfect for those quick-n-dirty snippets and stuff which lives just for some weeks, during the work on one scene, but is not worth elaborating into a full-blown piece of code $\endgroup$
    – Ichthyo
    Feb 11, 2019 at 1:40
2
$\begingroup$

Here are two variations on the answers given by Patan and sambler that some may prefer.

Variant of Sambler's answer

If you care about in-Python-console logging, but not availability/persistence of variables, then this approach is a slightly simpler alternative to sambler's answer: (run this in the Python console)

bpy.data.texts["NameOfScript"].as_module()
Variant of Patam's answer

If you care about in-Python-console logging, but not availability/persistence of variables, then this approach is an alternative to Patam's answer: (use this as your in-Blender "launcher" script)

import sys
import bpy

# this code block will redirect calls to print() to show up in the Python-console panel
class StdOutOverride:
    def write(self, text):
        sys.__stdout__.write(text) # also send to standard-output (can comment this out)
        if text != '\n': # ignore extra stdout.write('\n') call at end of each print()
            for line in text.replace('\t', '    ').split('\n'):
                for area in bpy.context.screen.areas:
                    if area.type == 'CONSOLE':
                        with bpy.context.temp_override(area=area):
                            bpy.ops.console.scrollback_append(text=line, type='OUTPUT')
sys.stdout = StdOutOverride()

filename = "/full/path/to/myscript.py"
exec(compile(open(filename).read(), filename, 'exec'))

I prefer this last approach myself, as it lets you get logging in the Python console, while still being able to use the convenient "Play" button in the script-panel's toolbar. (and this way there's less conflict, in case variable-names in the script overlap with whatever code I may be iterating on in the Python console)

$\endgroup$
1
  • $\begingroup$ This is great! I love not having to look at the console output in a separate window. But the feedback doesn't show up in the python console until the script has finished running, which makes it less useful for long scripts (e.g. looping through a series of renders). I was able to get more updates using bpy.ops.wm.redraw_timer(type='DRAW_WIN_SWAP', iterations=1) but that comes with performance issues and throws a warning each update. Are there any other methods to updating the python console in ~realtime? $\endgroup$
    – splic
    Nov 30, 2023 at 20:04

You must log in to answer this question.

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