11

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

Sam Quintanar
  • 151
  • 1
  • 4

3 Answers3

13

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'))
ideasman42
  • 47,387
  • 10
  • 141
  • 223
4

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.

sambler
  • 55,387
  • 3
  • 59
  • 192
  • 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 – Ichthyo Feb 11 '19 at 01:40
2

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)

Venryx
  • 143
  • 5
  • 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? – splic Nov 30 '23 at 20:04