AttributeError: __exit__ from custom operator

Hello lovely Blender coders.

Wondering if someone could give me a troubleshooting suggestion on why this might be happening. My custom operator is giving me a AttributeError: exit when it tries to run. It reads the function that I built fine, but it just won’t execute. I’m just building an interface that I can use to scan repositories for updates (like, a dropbox folder or something) and then import that object from a .blend library or a file.

Relevant code:


class CustomClass(bpy.types.Operator)
    bl_idname = "my_magic.btn"
    bl_label = "Find the unicorns"
    bl_description = "Finds the most magical of all the unicorns"

    def execute(self, context):
        if bpy.context.scene.customProp_1:
            if context.scene.customProp_2:
                scan_for_unicorns(context.scene.customProp_2, "horn")  # the line that I get the error on
        return{'FINISHED'}

I think it has to do with threading? It’s most probably a my misunderstanding of Python and Blender’s API. I’m new to both of them, but not new to coding (C# background).

My other thought is I have a wrong attribute attached to bpy.data. In my function I have bpy.data.movieclips.load(filepath) and followed what was said on the API in terms of data_from and data_to.

Maybe all I need is something like scan_for_unicorns.close()? Ugh, I dunno. Going in circles.

Any help greatly appreciated!

Could you please post the complete error? With traceback?

If you’re using threads, don’t use threads. Blender doesn’t do threading. It’s as easy as that.

Please don’t take this too personal: What are we supposed to make of “Hey, why am I getting this mystical error message from a method I called scan_for_unicorns?”

Bayesian: Sorry about the unicorn reference. I was away from my desk when I posted this, so I couldn’t copy paste code. I thought the functions were arbitrary, so…unicorns.

Here’s the full traceback now that I am back at my desk:

Traceback (most recent call last):
  File "/ clipImporterc.py", line 103, in execute
  File "/clipImporterc.py", line 78, in scan_files
AttributeError: __exit__


location: <unknown location>:-1


location: <unknown location>:-1

So it’s calling my scan_files function, which looks like this:


folderpath = bpy.path.abspath(folderpath)for file in os.listdir(folderpath):    filepath = folderpath + "\\" + file
    with bpy.data.movieclips.load(filepath) as (data_from, data_to):  # this would be line 78
        for name in eval("data_from" + datablock):
            my_item = eval("bpy.context.scene" + datablock + "_directory_list.add()")
            my_item.name = name  # these two correspond to custom props group
            my_item.file = file

And this would be the execute:


def execute(self, context):    if bpy.context.scene.dir_clip:
        if context.scene.folderpath_clip:
            scan_files(context.scene.folderpath_clip, "clip")  # this would be line 103

It’s good to know that Blender doesn’t support threading. I don’t have any implemented, but I thought maybe it was something I could try to fix it.

I shall be off to continue to debug.

I’m not sure what you are trying to accomplish. As I am writing this I am still scratching my head to decrypt your intentions :wink: . But Because I have recently seen another example of abusing eval, let me tell you loud and clear: If you are using eval, you are probably doing something very wrong!

At the very least it makes stuff unnecessarily harder. If you have a string and you want to retrieve an attribute of a certain object by that name, try getattr(my_object, attribute_name). For example getattr(bpy.context, “scene”) In the case of your code I can’t really decipher what you are trying to do.

On to your error message. It looks a bit like there are errors in your eval statements, because there are exceptions without line numbers.

The more important point is that these blender data objects don’t follow the context manager protocol. They don’t have enter and exit methods. Which means you shouldn’t be able to use “with movieclip as (a,b):” I’m also a bit at a loss why you think you can deconstruct that context into “data_from” and “data_to” and how that follows from a movieclip object. Again, I have no clue what this supposed to do.

Oh! Okay, I’ll look into not using eval. I’m hacking and slashing this guys script, which is why I’m using eval in the first place: http://vincentgires.com/tools/blender/addons/blend_library/v032/blend_library.py. Could give you a better idea of whats going on.

I wasn’t sure how to go on beginning making a custom importer, and this guy had a super sweet library importer. So to try and learn I’ve been working with what he had written. Maybe this will give everyone a better idea of what I am trying to accomplish?

Again, just making a custom importer than can scan directories (like a dropbox or something that gets updates), giving me a list of what’s available, and then importing my selected choice.

So yes, I’ll take a look at the eval statement. That could very well be the problem. I should mention that I do have this sort of thing working with .blend libraries which was what the script was originally for. Which is why I thought it might be my misuse of datablocks or my misunderstanding of the import os.path.

The plot thickens…

If you carefully look at the documentation, it clearly says that bpy.data.libraries.load() returns a context manager with two library objects. The bpy.data.movieclips.load returns a single movieclip object, no context manager, and no “data_from” or “data_to”.

I haven’t looked too closeley at this older import script, but yes, he does use eval. The thing is: I have much more experience with Python outside Blender than inside, and when I look at some people’s scripts I want to cry in pain.

And that makes total and complete sense. I just looked up the documentation…don’t know how ​I missed that. Additionally for anyone else being as silly as me, I did post this on stack exchange too. He confirmed the same, that I didn’t read the documentation closely enough. This fine person gave me a very thorough solution: http://blender.stackexchange.com/questions/28853/attributeerror-exit-error-on-custom-operator

So I’ll rework the script today and tomorrow with your suggestions as well, and hopefully the finished product won’t make you cry Bayesian. I appreciate you taking a look.

Please, don’t take my “smart ass” sounding reply as me accusing you of being silly. It’s only your code which was doing something silly, not you :wink:

Blender’s API Documentation is somewhat obfuscated, and it can take some time to find what you need, if it even is there.

I’m only kidding when I complain about crying. But that particular example is so … strange. I mean this “code interpolation” stuff with eval feels like constructing SQL code in PHP, while there are other much more “pythonic” ways, which are actually easier to use. I mean, we are talking about Blender, so information security is pretty much blown as it is, but if you were to use code like this in a website, you’d risk introducing all kinds of bugs and backdoors, if someone can manipulate the variables that go into these code strings.

Maybe it was an expert C programmer who wanted to emulate a preprocessor or something. Brilliant people, that folk. But sometimes they don’t get Python :wink: