2
$\begingroup$

This question is just a stackoverflow copy since I've just figured a specific Blender Stack Exchange was existing ! Thanks for your help.

Am I crazy or is there some bug with this feature (using python script with blender running in background) ?

1/ Copy / paste the following code (from screenshot.py) inside Blender (switch to Scripting view) and it will take a screenshot but ...

2/ Call this script from command line : (so you can automatize screenshots while you're modifying the scene with your script(s) ... for your blog, a tutorial, etc.)

blender --background --python screenshot.py

And it will crash without giving informations about what is "incorrect" in the context

screenshot.py :

import os, sys

#FIXME: Blender creates screenshot using python but not when running in background
#
# Same result from Ubuntu stock version (2.76) and from ppa (2.78)
#
# Within Blender : unable to fix this last warning but screenshot is generated !
#
#Traceback (most recent call last):
#  File "/usr/share/blender/2.78/scripts/startup/bl_ui/space_text.py", line 32, in draw
#    text = st.text
#AttributeError: 'SpaceView3D' object has no attribute 'text'
#
# From command line (crash) : blender --background --python screenshot.py
# Unable to determine what's wrong in the context
#
#Traceback (most recent call last):
#(...)
#File "/usr/share/blender/2.78/scripts/modules/bpy/ops.py", line 187, in __call__
#    ret = op_call(self.idname_py(), C_dict, kw, C_exec, C_undo)
#RuntimeError: Operator bpy.ops.screen.screenshot.poll() failed, context is incorrect

def screenshot(P_filename, P_path = None):
  import bpy

  L_saveAs = P_filename
  L_saveAs = os.path.join(P_path, L_saveAs) if P_path else os.path.join("/tmp", L_saveAs)
  print("Scene saved in " + L_saveAs)

  #XXX: switching to 3D full view = maximize scene in main window
  #bpy.context.window.screen = bpy.data.screens['3D View Full']
  for window in bpy.context.window_manager.windows:
    screen = window.screen
    print("Window : " + str(window.width) + "x" + str(window.height) + ":" + str(window.x) + "," + str(window.y))
    print("Screen : " + str(screen.name) + ", Scene : " + str(screen.scene.name))
    #for area in bpy.context.screen.areas:
    for area in screen.areas:
      print("Area   : " + str(area.type))
      if area.type == 'VIEW_3D':
        for space in area.spaces:
          print("Space  : " + str(space.type))
          if space.type == 'VIEW_3D':
            #space.viewport_shade = 'RENDERED'
            for region in area.regions:
              print("Region  : " + str(region.type))
              if region.type == 'WINDOW':
                L_altBpyCtx = {                        # defining alternative context (allowing modifications without altering real one)
                  'area'      : area                   # our 3D View (first found)
                , 'blend_data': bpy.context.blend_data # just to suppress PyContext warning, doesn't seem to have any effect
                #, 'edit_text' : bpy.context.edit_text  # just to suppress PyContext warning, doesn't seem to have any effect
                , 'region'    : None                   # just to suppress PyContext warning, doesn't seem to have any effect
                #, 'scene'     : bpy.context.scene
                , 'scene'     : screen.scene
                , 'space'     : space
                , 'screen'    : window.screen
                #, 'window'    : bpy.context.window     # current window, could also copy context
                , 'window'    : window                 # current window, could also copy context
                }
                bpy.ops.screen.screenshot(L_altBpyCtx, filepath = L_saveAs, full = False)
                break #XXX: limit to the window of the 3D View
            break #XXX: limit to the corresponding space (3D View)
        break #XXX: limit to the first 3D View (area)

screenshot("screenshot.png", ".")

3/ By the way, call it without the --background argument and it will generate an empty screenshot (size of your window, full of default color, gray in my case). In the meantime, uncomment

#bpy.context.window.screen = bpy.data.screens['3D View Full']

and/or

#space.viewport_shade = 'RENDERED'

And you'll see your Blender interface being affected (switching layout of your views from 'Default' to '3D Full View' and/or your viewport shading from 'Solid', by default, to 'Rendered') ... so the script is actually interpreted but it does not generate the screenshot !

No matter what, the problem seems coming from calling Blender with "--python somescript.py" directly from the command line

I'm probably missing something ?! Thanks for your help

$\endgroup$
3
$\begingroup$

Got the answer from a Blender guy (thanks sergey). Bottom line : it's a limitation since all the scripts passed via command line argument are executed at command line processing time, prior to any OpenGL draw is done !

The warning is caused by script trying to trick the system and override the context, that context is likely in inconsistent state. When running screenshot from the interface you don't need to override any of the contexts.

All the scripts passed via command line argument are executed at command line processing time, prior to any OpenGL draw is done. The screenshot operator itself is just reading OpenGL buffer,m without doing any actual drawing (it can't draw anything since that'd be unsafe).

When running blender in background mode, there is no window created, which also means there is no OpenGL context. You can;t use screenshot in such configuration.

So thanks for the report, but it's just limitation which can not be easily bypassed.

Precision : (since the provided code do not show all the attempts made trying to "trick" Blender)

Sadly, if you are also / still interested in such feature, you'll have to think outside (Blender) box ! Don't waste your time trying to "trick" Blender, like delaying script execution, playing with application handlers, faking script import in a Text editor, etc. ... I've done it for you : it doesn't work, probably for a very similar reason.

$\endgroup$
  • 1
    $\begingroup$ surely that's the reason to have bg mode, not to have the UI overhead. $\endgroup$ – batFINGER Jul 7 '17 at 13:27
  • $\begingroup$ Yep, but do not help when you're trying to take a lot of screenshots of that UI (multiview, multiaxis, step-by-step) in a 3D printing context (programmatic modeling). Since this limitation is not only affecting bg mode but all scripts launched from command line $\endgroup$ – Another Tux User Jul 7 '17 at 13:35

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.