Python generation script doesn't work
-
Hi!
Cinema 4d 2023.2 Redshift 3.5.20
Problem with a python script. This script is organized as follows: it turns object visibility on and off and starts rendering. And it renders as many images as I set it to render.
The script runs only when Picture Viewer is running. You can render one picture and leave it open
In addition, it produces a .json file.There are two txt files: x - file with exceptions. These combinations cannot be used
It looks like:
gl_21 mask_7
gl_21 jw_27
gl_21 jw_24
gl_21 jw_9File x2 - here the number of objects is specified.
glasses NULL 4
glasses gl_21 3
glasses gl_20 5
glasses gl_18 3
When you run the script, you need to specify these filesThe problem is as follows. If the x2 file is empty or with one line, the script renders images and .json files
If there is more than one line in the x2 file, one picture is rendered and the program just hangs. And does not produce json. It does not have time to write anything in the log. The line is loaded a little bit and everything hangs (attached picture)
I could not find the error, debugger says that there are no errors
What could be the problem?
The problem is that at the stage of creating a json file everything hangs up with an x2 file that is more than one line full.. Nothing can be written to the Console Log. It hangs before
project_redshift.py -
Hello @eegoridze,
Welcome to the Maxon developers forum and its community, it is great to have you with us!
Getting Started
Before creating your next postings, we would recommend making yourself accustomed with our forum and support procedures. You did not do anything wrong, we point all new users to these rules.
- Forum Overview: Provides a broad overview of the fundamental structure and rules of this forum, such as the purpose of the different sub-forums or the fact that we will ban users who engage in hate speech or harassment.
- Support Procedures: Provides a more in detail overview of how we provide technical support for APIs here. This topic will tell you how to ask good questions and limits of our technical support.
- Forum Features: Provides an overview of the technical features of this forum, such as Markdown markup or file uploads.
It is strongly recommended to read the first two topics carefully, especially the section Support Procedures: Asking Questions.
About your First Question
I would like to point you to four sections in our Support Procedures:
Scope of Support: "It doesn't work" is not a support request and we cannot debug your code for you, but instead provide answers to specific problems.
Asking Questions: Repeatable: Your claims or problem should be repeatable for us. In most cases this means posting executable code which demonstrates your problem, with the emphasis being on executable. We should be able to paste this code into an editor and then run or compile it without having to write code ourselves. When you just post snippets, this usually means that we will not run your code, as we do not have the time to invent all the code around it. Ignoring this also comes with the substantial risk that you do not post the code which contains your actual mistake/problem..
Asking Questions: Sparseness: Your problems should be sparse, or in other words you should spend some time on boiling down more complex problems. When you, for example, are writing a plugin with which one can create trees with physics and all sorts of fancy things, and you run into a problem, you should spend time on removing as many fancy things as possible, so that we have an easier time helping you. Code examples should only very rarely have more than one thousand lines of code.
Reporting Bugs & Crashes: The whole section applies here.
While it is understandable that users sometimes violate some of these rules, it is here a bit much.
- Sparseness: You certainly could have spent some time on pruning your script from things you can remove without removing your problem.
- Repeatable: We cannot run your code. While you have provided the source code, you have not provided the scene file and possibly other files which are necessary to run this.
- Reporting Bugs & Crashes: When you have provided (2), you should follow the pattern we require to report bugs and crashes, even when they are your own. It is all about reproducibility and clear instructions.
General Advice
It is obvious that you have put quite some work into your script and also work into your question here. Thousands lines of code do not write themself and screenshots also do not make themself.
But my major advice would be here: "Be more strategic about how you approach things." Writing software is all about breaking things into manageable problems and you seem to try to do everything at once. Which is fine if you are a pro and never make mistakes, but it usually bites you royally in the butt when you run into problems.
Remove Non-Const Code from Module Scope
In the first 100 lines you have a lot of code in the module scope. You can initialize global constants in the module scope, but you should certainly not open dialogs there. This is just a big no-no as it not only makes your code hard to read - when is happening what, you cannot just start reading in the main function -, but also comes with the problem that some of the code will run when the module is initialized and some when the execution context
__name__
is"__main__"
.
Divide and Conquer & Abstract
There is very little abstraction in your code, which again is fine when you are pro who never makes mistakes, but becomes a problem when you must debug things, as you then have to deal a monolithic piece of code where it is hard to turn off things or understand what is happening. When I take the first lines of your
main
function:
If I would rewrite this, it would look like this:import c4d import mxutils class ObjectGroup: """A class to group objects and set their visibility. """ def __init__(self, groupName: str, parent: c4d.BaseObject) -> None: """Initializes the class. """ self.groupName = groupName self.objects = mxutils.CheckType(parent, c4d.BaseObject).GetChildren() # It seems a bit questionable to me to store the names of the objects in a separate list, # since the data is so easy to access on a node, but I went with it here. self.names = [i.GetName() for i in self.objects] self.SetVisibility() def SetVisibility(self, state: int) -> None: """Sets the editor and render visibility of the objects in the group. """ for obj in self.objects: obj[c4d.ID_BASEOBJECT_VISIBILITY_EDITOR] = state obj[c4d.ID_BASEOBJECT_VISIBILITY_RENDER] = state def __iter__(self) -> tuple[str, c4d.BaseObject]: """Iterates over name, object pairs. """ for name, obj in zip(self.names, self.objects): yield name, obj def __getitem__(self, index: int) -> tuple[str, c4d.BaseObject]: """Gets the name, object tuple at the given index. """ if index < 0 or index >= len(self.objects): raise IndexError("Index out of range.") return self.names[index], self.objects[index] def GetObjects(doc: c4d.documents.BaseDocument) -> dict[str, ObjectGroup]: """Gets the objects from the document. """ # Get the objects from the document, be defensive about our assumptions, here we assume that # the document contains at least eight objects, but we should check it. objects: list[c4d.BaseObject] = doc.GetObjects() if len(objects) < 8: raise ValueError("The document must contain at least eight objects.") # Now we create one data structure to hold all the object groups, this makes it easier to use. # I personally would crate a class to hold the object groups, but I went with a dictionary here # to keep it simple. return { "glasses": ObjectGroup("glasses", objects[0]), "masks": ObjectGroup("masks", objects[1]), "jewelery": ObjectGroup("jewelery", objects[2]), "headgear": ObjectGroup("headgear", objects[3]), "clothes": ObjectGroup("clothes", objects[4]), "hairs": ObjectGroup("hairs", objects[5]), "eyes": ObjectGroup("eyes", objects[6]), "special_accessories": ObjectGroup("special_accessories", objects[7]) } def main(): """ """ # Now can just call #GetObjects and get the data we need. data: dict[str, ObjectGroup] = GetObjects(doc) # Now we continue in this style, where we "divide and conquer" the problem, i.e., split things # into sub-problems and solve them one by one. So that we can have here in the main function only # the high-level logic. restrictions: list[str] = GetRestrictions(RESTRICTIONS_FILE) ApplyRestrictions(data, restrictions) # ...
Doing this will help you to help yourself, as you would get more control over your own code.
Conclusion
Some of my colleagues are a bit less squeamish than me when I comes to spaghetti code, but I doubt that they are willing to debug your 800 lines of single letter variables.
Try to make your code more abstract and clean, you will likely fix the problem yourself in the process. For me it is currently not really possible to follow your code and with that give you meaningful advice.
If not, come back with a pruned version of your code, provide all data, and reproduction steps. And with pruning I mean really prune it. Try to remove as many things as possible. You should also be verbose about what your problem is. I think you are encountering freezes, "the program just hangs" but you only mention that somewhere in the middle of your posting.
Cheers,
Ferdinand