Hi guys, I am working on a larger script in python and have a question regarding making definitions and their needs of libraries.
Is it OK to import the libraries a def needs even though it is already imported? Or should I ONLY import them once during a script?
The thing is that I need to make the definitions first in simple scripts to easily bugtrack them, (I am a simple guy ) so it is easy to import all the needed stuff in the def and then copy-paste that def into the final assembly, but then I would end up importing āRhinoā, āscriptcontextā, ātimeā and all the other stuff multiple times. So is that āharmingā anything? Or is python smart enough to just skip that if it is already imported?
So basically as long as I import the libraries as they are, or as the same name each time it will be fine.
(like āimport rhinoscriptsyntax as rsā each time)
Keep imports on top of your file. There is (almost) no reason to do an import within a function.
If you want to test single functions, keep them in your module, import your module and execute the function from your library inside the script editor. Instead of testing each function manually, also think about unittests. Separate GUI interaction (=ViewModel) from Core (=Model) logic. Getting geometry and input arguments and outputting them, has nothin to do with creating, modifying or validating geometry. It shouldnāt matter if you call it from a Rhino Command or a Grasshopper Component (ideally).
Oh⦠thanks! But that was a lot of terms that I am unfamiliar with
What I am working on is Holomark3 where I want to run 6 CPU tests and 6 GPU tests + render tests and then the score handling and system data gathering.
I keep them separate when I program them to keep everything easy to maintain for my brain. So I put the data in a definition and call that. Then I put all those definitions in one final script at the end and compile that to a plugin.
Do you think I should do it differently? Itās important for me to do this as simple as possible so I can work on it every now and then without getting lost in my own complexity
I donāt get the second step. Is the command-compiler not able to deal with modules?
Usually you split a larger piece of code into smaller files until it fullfills the āSingle Responsibiltyā rule.
If you programm object-oriented you put 1 class into 1 file. And this one class usually does only one major thing. But even without classes, the idea is to separate concerns.
Each file has its own dependencies. Of course reducing the dependencies is a good thing. Dependency inversion/injection. Your module/component/class shouldnāt rely on too many external code. Instead you design it to deal with abstractions instead of concrete implementations.
If you encapsulate well, (unit) testing is simple. Sounds complicated but is actually really easy. And this helps dealing with many lines of code.
Example: You donāt need to run 6 cpu and 6 gpu tests to see if the report is written correctly. If you encapsulate the reporting into a Report class (or reporting module), you can test that totally isolated. Of course the arguments for writing the report have to be abstract enough to be mocked.
It is definitely good practice to put all your imports at the top of the file, starting with standard library imports like os, csv, sys and following on with things like Rhino and your own submodules and to organise your code in functions in separate .py files and import the functions you need into your main file
from Holomark3 import CPUTest1, CPUTest2, ...
def main():
CPUTest1()
CPUTest2()
if __name__ == '__main__':
main()
The main gotchas to look out for are any code which is executed during import (should be in the __init.py file) and overwriting names, for instance if you import Rhino and also Rhino.Geometry as rg etc then depending on the order of import, later import statements may not work properly. Overall you should be fine.
Also you can use a tool like isort to sort your imports - you will need a separate Cpython installed on your system but it should work fine
Nice, that was visually easy to understand.
So can I just import any .py file that is located at the same location as the running .py file?
And if so do I just put those files together in the compiler, or do I just put the āmotherā .py file there and the compiler reads everything it needs from it??
Sorry for being a total n00b at this, I have evolved from a macro user to a simple scripter who does way to much with way to little coding knowledge
No worries Iām on the same journey really but probably with much more deliberate python learning thrown in (books, podcasts, online courses, knowledge sharing hereā¦)
Yes you can put all the python files next to one another, however Iām not sure about packaging them with the compiler - there was some discussion about this over the last many years on this thread which suggests that it is possible to put multiple files side-by-side and includes a video and a plan to write some documentationā¦
It is also possible to add other files to the zip (The installer is just a renamed zip file) and then all of those are installed to the same location. I do that with display modes and rhino files that are used for content and templates for Holomark2 (and will for HM3 too of course)
I do recommend coding this way in general where you break up your logic into easy to understand libraries of files. Unfortunately, the script compiler is not currently set up to be able to include packages. Itās been on my todo list for a long time.
Scripts are currently embedded as strings inside of commands. This means there is no local working directory where the script is executing as there is no python file.
Ahh I might be a bit out of date - because rhino packages were zip files I thought the ability to directly import from a zip file might help but that may not be the case for yak? I also had vague ideas around using the built-in python tokeniser and getsource modules to flatten a package into one string or file but couldnāt find an existing robust looking open source example. I have played with these a little to correctly handle the import statements and docstrings in my rhinoscriptsyntax getsource utility. ā¦
I have been discussing this with my local Python user group - what path do you use to find your image assets from python? (sorry this is surely in the docs somewhere)
If you start your script with
import sys
path_to_assets = r'path\to\assets' # not literally, obvs
sys.path.insert(0, path_to_assets)
from Holomark3 import CPUTest1, CPUTest2, ...
Does that work ? The idea is to add the correct path so Python can find the other filesā¦