Is ObjectIterator() parsing depreciated under R23 and higher?
-
Hello folks,
I trying to update a plugin which has been developed for C4D R21.x and Python 2 to C4D R23 and higher which is running Python 3. I got almost everything working now except a redundant issue I'm getting with
ObjectIterator()
parsing. So, I wondering if the use I made of it is wrong, or if this lib is depreciated?Here the code running under Python 2 without any issues on C4D R21,
def RetreiveTags(self): self.tagList = [] obj = self.cacheDoc.GetFirstObject() scene = ObjectIterator(obj) for obj in scene: tags = TagIterator(obj) for tag in tags: self.tagList.append(tag)
But while I'm running the same code under C4D R23 with Python 3 I'm getting this error:
Traceback (most recent call last): File "TestIterator.pyp", line 204, in CoreMessage self.RetreiveTags() File "TestIterator.pyp", line 160, in RetreiveTags for obj in scene: TypeError: iter() returned non-iterator of type 'ObjectIterator'
The line in error, is the one with the
for tag in tags:
After some readings, especially this one http://cgrebel.com/2015/03/c4d-python-scene-iterator/ , I assume that the error comes from the
raise StopIteration
Is there a way to get this library works normally as it was under R21 or should I update the code like I already did with my own iterator for object list?
Any advises are as usual more than welcome!
Thanks a lot,Christophe
-
I went a but further in this old code and discover that the plugin was based on the class I linked in my previous post.
There is now better ways to get the same result withBaseObject.GetTags()
. I simply got rid of this class and change the code to parse everything.
Done.Cheers.
-
Hello @mocoloco,
thank you for reaching out to us. We did reactivate this topic because we do think it contains a problem that might be relevant to other users.
First of all, we would like to point out that this question is formally out of scope of support, since it is about third-party code and why it is not working. Please refer to the Forum Guidelines for details on what is eligible for support and what not. We cannot debug third party code for users.
In this case however, one can see the reason immediately, due to the code being quite short and you providing a link. The code for the class
ObjectIterator
has been written in 2015 for Python 2 and is still using the old object interface of Python. With R23 Cinema did move to Python 3 and therefor also to the new object interface. You listR21
andR23
as versions in your tags. I would expect this code to work inR21
(which has a CPython 2 interpreter), but not inR23
(which has a CPython 3 interpreter).Cinema is throwing
TypeError: iter() returned non-iterator of type 'ObjectIterator'
when you try to runfor obj in ObjectIterator(obj):
. What is happening is thatin
will invoke the__iter__
implementation ofObjectIterator
which just returns a reference to the object itself. The interpreter then looks for__next__()
in your object and cannot find it, then throwing this error. Python 2.x'snext
has changed to__next__
with Python 3.x. But there are also other changes, which will make that code not work if you do just change the name of the methodObjectIterator.next
toObjectIterator.__next__
. We cannot provide here support on learning Python, I would suggest reading content on the difference of theobject
interface between 2.x and 3.x. However, a minimal solution for your case could look like this:class Iterator(): """A minimal Python 3.x conformant iterator implementation. """ def __init__(self, data): self._data = data def __iter__(self): for item in self._data: yield item for item in Iterator([1, 2, 3, 4, 5]): print (item)
Cheers,
Ferdinand -
Hello @ferdinand, thanks a lot for your time and reply.
I indeed discovered that the code was for Python 2 when I went I bit further in the code analysis.
I thought it was a c4d library, and that's was my mistake and indeed it was totally out of the scope to place it here; sorry.
In the meantime, I got rid of that class and made my own iterator method - not a class itself like you did to update the old one (but that's also a good idea).It was quite easy to iterate all the tags by simply use
GetTags()
which gives the following,tags = obj.GetTags() if tags is not None: for tag in tags: print (tag.GetTypeName() + " found") self.tagList.append(tag)
Thanks for your time!
Christophe -
Hello @mocoloco,
without any further replies or questions, we will consider this thread as solved by Thursday and flag it accordingly.
Thank you for your understanding,
Ferdinand