Hello - I’m seeking advice on the best practices for importing Python libraries into GHPython when using external Python modules. As I’m new to managing Python code across both Grasshopper and external sources, I would greatly appreciate suggestions.
We host our Python functions remotely and pull them into a local directory as Python files, allowing users to access these functions within Rhino/Grasshopper. This setup allows us to manage development and versioning separately from Grasshopper, so any updates don’t require everyone to replace user objects each time. These files are then imported into GHPython components, and we have a tool that handles Python library installations via Rhino’s pip.
My question is, I’m unsure where to manage Python dependencies—should they be imported within the external files or directly in Grasshopper? Or both? I’ve observed that to prevent errors entirely, I often need to import the same libraries both in the external files and in Grasshopper. For instance, even if a library is imported in GHPython, I still may encounter ImportErrors unless the same import statement is also included in the external file.
Here are my questions:
I would like to understand why this happens. If GHPython is executing the code, surely it should handle imports. Why would GHPython demand duplicate import statements in the external file? (I also tested this with importing only in the external file and not in GHPython. This also created errors. Only importing in both locations permanently resolved all import issues.)
I am interested in finding out whether there is a more streamlined method to manage imports to avoid both errors and the redundancy between GHPython and external Python files.
Any insights & suggestions would be greatly appreciated! Thanks in advance.
Thank you very much Anders. I hope it’s okay that I’ve adapted your graphic to clarify the issue I encountered. I am using Rhino8 Grasshopper Python3 (I referred to this as GHPython in my post).
To be fair, the issue doesn’t seem to affect all libraries unanimously, but I haven’t yet gone through the exercise of checking each import one by one. As a temporary solution I duplicated all the imports to suppress any ImportErrors. I was hoping to understand reasons why these errors might occur, so I could go back and address the redundancy armed with some knowledge.
Below is an example of one ImportError that I noticed consistently, affecting the ghpythonlib.treehelpers module. Initially, I imported the module solely in the external file (as shown in your image) but this led to the error below. Conversely, ‘module not found’ errors occurred when I attempted to import solely in GHPython. To resolve this quickly, I imported everything in both the external file and GHPython - a temporary solution which doesn’t allow me to manage the imports remotely.
File "C:\Users\{{user_name}} \AppData\Roaming\\{{file_name}}.py", line 410, in {{function_name}}.
import ghpythonlib.treehelpers as th
File "C:\Users\{{user_name}} \.rhinocode\py39-rh8\site-rhinoghpython\ghpythonlib\__init__.py", line 14, in <module>
from ghpythonlib import treehelpers
File "C:\Users\{{user_name}} \.rhinocode\py39-rh8\site-rhinoghpython\ghpythonlib\treehelpers.py", line 4, in <module>
from Grasshopper import DataTree as Tree
ImportError: cannot import name 'DataTree' from 'Grasshopper' (unknown location)
No worries, that’s great. I’m afraid I haven’t really tested importing much with the new script editor, but maybe @eirannejad (it’s developer) or @michaelvollrath (a Rhino 8 script editor “super user”) might be able to help.
Just made a small edit to prevent further misunderstanding. It’s admittedly a bit confusing with so many different editors, languages, runtimes, and versions
To make sure Python (3 or 2) that is running inside of Rhino can find your modules living in an external folder, you would want to add the folder path of where the modules are (not the module itself) to the Search Paths in the editor configuration.
The example component below is importing module mymod from an external folder and calling a module function. The module source is the darker box at the bottom of the image. Notice that it can import ghpythonlib
Hi Ehsan, thanks very much for this suggestion. I did not think to check the path logic.
I have automated pulling the external module from the remote repository to a specified path in ‘AppData\Roaming’. I then ensure this path is appended to sys.path, which allows me to call the module from Grasshopper.
While this method successfully imports the external module, perhaps it causes some of those secondary references to break? It looks from your image that there may be a separate Grasshopper-specific path list.
Let me do some tests and I will jump back on the thread. My code is quite distributed - I will try to replicate the issue within a smaller sample first. (As I probably should have done sooner. )
Still open to ideas and theories! Hearing others’ thoughts is incredibly helpful.
Importing Grasshopper modules when running python scripts in the terminal and outside of Rhino is going to fail. Grasshopper is only available inside of Rhino
Grasshopper 1 and 2 have similar namespaces. Let me know if you have Grasshopper 2 installed/loaded
The python path configurations in the editor are not Grasshopper-specific. They affect the python 3 or 2 runtime across Rhino.
Only just that one can also always use the sys.path.append method to explicitly add paths within a Python script itself (i.e. prior to importing). That might help with your importing goals:
import sys
# Point to a folder with Python modules in it
myPath = r"C:\Users\ander\OneDrive\Desktop"
# Add to the folder importable paths if it's not already in there
if myPath not in sys.path:
sys.path.append(myPath)
# Check folders you can import from
for p in sys.path:
print p