2

I'd like to be able to use an external instance of Python (ie. not Blender's internal python) to read a blend file and inspect it for Render Settings (ie. Start Frame, etc.).

Is this possible without firing up the Blender app itself? I don't want to have to depend on a Blender app, or to import the bpy module because the main project is in Python 2.7.

Also, I'd like to avoid any cli calls to blender to get this information.

Todd McIntosh
  • 9,421
  • 25
  • 50
  • I believe not, but from the source code of blender it is possible to compile a only a standalone bpy. IT can do the trick for you. – Mörkö Sep 16 '15 at 05:54
  • Looks like it is possible by inspecting the file on a byte level, and by knowing the byte address of the specific data value that you want. More info here: http://www.atmind.nl/blender/mystery_ot_blend.html. Once I figure out the specifics I'll post more. – Todd McIntosh Sep 16 '15 at 06:23
  • 5
    Check out http://blender.stackexchange.com/questions/3141/get-number-of-frames-in-scene-from-the-command-line – batFINGER Sep 16 '15 at 12:48
  • What settings do you need? - (ie. Start Frame, etc.). is too vague. – ideasman42 Sep 16 '15 at 17:27
  • I'd be happy with Start Frame, End Frame, and output File Format to begin with. – Todd McIntosh Sep 16 '15 at 18:16
  • Also, the calling Python needs to be a 2.7 version, and can't be Python 3, so I don't think I can import bpy as a module because of this correct? – Todd McIntosh Sep 16 '15 at 18:20
  • I'll be experimenting with both blender-aid and the blender-file python package, my objective is to consistently get a parsed .blend file with some structured data format just using a blender addon. – Pedro Almeida Mar 28 '23 at 03:48

2 Answers2

4

While it is possible, using blender will be much easier. A small script that you pass to blender when run from a cli is small and easy to maintain. From another python script you could automate it with -

from subprocess import call
call(['blender','-b','file.blend','-P','script.py'])

You can even have your script generate the small temporary script that gets passed to blender.

However if you really have a need to not require blender to be installed, you may want to look at an old project that appears to have died off called blender-aid, it provided a web interface to blend files and used a python script to access data in the blend file, it was intended to assist project management and allowed file links to be repaired and/or re-factored, so apart from reading a blend file it could also write changes to them. While the full info of reading a blend file is contained within blender's source code, you may be able to get a start with blender-aid's old script here - or at least it will give you an idea of how much code is needed.

sambler
  • 55,387
  • 3
  • 59
  • 192
2

I've found a solution that works the way I need for my project. A big thank you to sambler for pointing me in the right direction towards the blenderaid project which allowed me to get the results I needed.

Here's how I did it:

  1. I downloaded the blender aid package, renamed the folder from "blenderaid-py-20110211-2" to just "blenderaid" and placed the folder in the /lib folder of my project
  2. I added init.py files to the /lib and /lib/blenderaid folders
  3. In my root folder I created a test.py file with the following code:

Update - I discovered that the block label for finding image type changed at Blender 2.61 - I updated code to add the if/then statement


import os
from lib.blenderaid.blendfile import *


TRANS=[
    "TGA", "IRIS", "HAMX", "FTYPE", "JPEG", "MOV", "UNKOWN", "IRIZ", "UNKOWN", "UNKOWN", "UNKOWN", "UNKOWN", "UNKOWN", "UNKOWN", "TGA", "AVI", "AVI", "PNG", "AVI", "MOV", "BMP", "HDR", "TIFF",
    "EXR", "FFMPEG", "FRAMESERVER", "CINEON", "DPX", "MULTILAYER", "DDS"
]

def formatImageType(value):
    if value<len(TRANS):
        return TRANS[value]
    else:
        return "UNKNOWN"


file = 'path/to/file.blend'


if file.endswith(".blend"):
    bf=openBlendFile(file)

    for block in bf.FindBlendFileBlocksWithCode("SC"):

        scStartFrame = block.Get("r.sfra");
        scEndFrame = block.Get("r.efra");
        scImageType = formatImageType(block.Get("r.imtype"))

        if bf.Header.Version>=261:
            scImageType = formatImageType(ord(block.Get("r.im_format.imtype")))
        else:
            scImageType = formatImageType(block.Get("r.imtype"))

    print scStartFrame, scEndFrame, scImageType
Todd McIntosh
  • 9,421
  • 25
  • 50