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.
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’m not sure what you are trying to accomplish. As I am writing this I am still scratching my head to decrypt your intentions . 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.
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.
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
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