Import your own modules in Grasshopper's Python development

Introduction

I wrote an article Using an external editor for Python development of Grasshopper, but when I try to develop a Python program in earnest with Grasshopper, one file Then the code will not fit, so you will want to separate your own functions etc. in a separate file. Also, when reading an image file or CSV, or when creating a plug-in, it is necessary to manage the file structure firmly so that the file can be referenced by a relative path. This time, I will explain how to make it easier to manage the code by using your own modules and configuration files.

** Advantages of dividing the program with self-made modules **

--Prevents the code from becoming too long and unmanageable --Easy to individually test your own functions and classes --By creating a configuration file, you can change the settings without having to mess with the code. ――It becomes easier to divert the function in another project --Packaging makes it easier to manage with git etc.

file organization

This time, I will explain with this file structure. There are `gh_file.gh``` and function.py``` directly under the project folder, and to call the module ``` mod.py``` in the folder `` module Create `` `__ init__. Py. Also, create `radius_range.json``` in the folder `data``` as a configuration file.

.
├── module
│   └── __init__.py
│   └── mod.py
├── data
│   └── radius_range.json
└── function.py
└── gh_file.gh

In this sample project, the following program will be used as an example.

--Use Pop2D with GH to generate multiple points at random locations --Enter a list of points in function.py --Call the mod.py function from function.py --Returns a random radius for each point in the range set by radius_range.json --Generate a circle with a random radius around each point with function.py

setting file

In the configuration file radius_range.json, the "minimum value", "maximum value" and "step" to be included in the random function are defined.

radius_range.json


{
    "min": 1,
    "max": 10,
    "step": 1
}

module

In the module `mod.py```, create a simple function that calls json in the configuration file and returns a random number. I would like to call this function called ``` random_radius``` from `function.py```.

mod.py


# -*- coding: utf-8 -*-
import json
from io import open
import random

def random_radius():
    #Relative path of json file
    path = "./data/radius_range.json"
    #open json file
    with open(path, encoding='utf-8') as f:
        d = json.load(f)
    #Get parameters from config file
    min = d['min']
    max = d['max']
    step = d['step']
    #Returns a random number
    return random.randrange(min,max,step)

Grasshopper settings

The GH file gh_file.gh is set like this.

In Read File, right-click F → Select one existing file to function.Specify py.


 Please refer to [Use an external editor for Python development of Grasshopper](https://qiita.com/keiwatanabe/items/9eb6a7d6749f5e586f7f) for the setting to read an external file.
 ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/263714/1f8b46bc-c4e4-a41d-84e7-474c58cd383f.png)

# GHPython file directory

 Now for the main subject, let's try the following code in function.py to understand why we are writing this article.


#### **`function.py`**
```python

import rhinoscriptsyntax as rs
from module import mod

a = mod.random_radius()

Then, I think that such an error will appear.

image.png

1. Solution exception:path'C:\Program Files\Rhino 6\System\data\radius_range.json'Some of them were not found.

When I read the error message, it says that radius_range.json cannot be found. I can call `mod.py``` because I have gone to the point of searching for the json file, but it seems that the json file has gone to search for Program Files```. I'm calling `` function.py in the same directory from a GH file in the same directory, but for some reason I'm referencing `` `Program Files. ..

** Why can't I refer to radius_range.json correctly even though mod.py can be read correctly? ** **

Module search path and current directory

To understand the cause, you need to understand the ** module search path ** and the ** current directory **.

Module search path

This is a list of paths that Python will look for when importing standard or external libraries. To check this, try the code below in the same GH file.

import sys
print(sys.path)

Then it will be returned like this. The 'Z: \\ Projects \\ demo-ghpython-package' at the beginning of this is the directory where I saved this project file and the location where the GH file is stored.

['Z:\\Projects\\demo-ghpython-package', 'C:\\Program Files\\Rhino 6\\Plug-ins\\IronPython\\Lib', 'C:\\Users\\[username]\\AppData\\Roaming\\McNeel\\Rhinoceros\\6.0\\Plug-ins\\IronPython (814d908a-e25c-493d-97e9-ee3861957f49)\\settings\\lib', 'C:\\Users\\[username]\\AppData\\Roaming\\McNeel\\Rhinoceros\\6.0\\scripts']

In other words, modules in the same directory as the GH file can be imported by following this path. Now you know why `` `mod.py``` could be imported.

Current directory

The current directory is where Python is running. To check this, try the code below in the same GH file as before.

import os
print(os.getcwd())

Then, in my case, the result is returned as follows.

C:\Program Files\Rhino 6\System

Apparently the Python code for the GH file was running inside Rhino 6 in Program Files. When referring to the json file, it was described as ** relative path ** like `` `./data/~~.json```, so look for the json file in the data directory in the above path. I said, there is no such file! It seems that an error occurred.

To read an external file correctly

There are two ways.

  1. Specify the external file with an absolute path
  2. Move the current directory

I think that it is better to specify it with an absolute path, but it works when the data is stored in the same project file like this time or when the same code may be executed on another PC. No. Therefore, this time we will use method 2.

Move the current directory

Change to `` `function.py``` to move the current directory as follows.

function.py


import rhinoscriptsyntax as rs
from module import mod
import os

#Get the directory containing the GH file = project folder
base_dir = os.path.dirname(ghdoc.Path)
#Move current directory to project folder
os.chdir(base_dir)

a = mod.random_radius()

-- ghdoc.Path returns the path of the GH file being executed, so in this case the directory path of that path will be the path of the project folder, so set it to `base_dir``` I will. --Move the current directory to `base_dirwithos.chdir```.

Then, a random number came back from a safely.

image.png

Added a program to draw a circle

Originally I wanted to output from a a circle object, so change the code to write a circle with the returned random number as the radius.

function.py


import rhinoscriptsyntax as rs
from module import mod
import os

#Get the directory containing the GH file = project folder
base_dir = os.path.dirname(ghdoc.Path)
#Move current directory to project folder
os.chdir(base_dir)

circles = []
for pt in pts:
    #Define a plane that draws a circle
    plane = rs.MovePlane(rs.WorldXYPlane(), pt)
    #Get a random radius
    radius = mod.random_radius()
    #Generate a circle and add it to the list
    circles.append(rs.AddCircle(plane,radius))

a = circles

The yen is finally returned. Although I worked hard, the result is sober lol image.png

at the end

This time it was a simple program that writes a random range in a configuration file, reads it using a module and passes it to the main program, but it is very effective when reading image files and a large amount of CSV. Please refer to it when creating a plug-in with Python.

reference

https://note.nkmk.me/python-os-getcwd-chdir/

https://note.nkmk.me/python-import-module-search-path/

Recommended Posts

Import your own modules in Grasshopper's Python development
[Python] logging in your own module
Create your own Linux commands in Python
[LLDB] Create your own command in Python
Easily use your own functions in Python
[Python] Package and distribute your own modules
Get your own IP address in Python
Framework development in Python
Development environment in Python
Slackbot development in Python
Create your own Big Data in Python for validation
Create your own Random Dot Stereogram (RDS) in Python.
Try to improve your own intro quiz in Python
Dynamically import / reload modules that have changed in Python
Use the CASA Toolkit in your own Python environment
[Road to intermediate Python] Define in in your own class
Dynamically import scripts in Python
Organize your Python development environment
Python development in Visual Studio 2017
Python development in Visual Studio
Try sorting your own objects with priority queue in Python
[Python] When you want to import and use your own package in the upper directory
Working with LibreOffice in Python: import
Web application development memo in python
Prepare your first Python development environment
Create your own graph structure class and its drawing in python
Specify your own class in class argument and return type annotation in Python
Modules and packages in Python are "namespaces"
[Python] Register your own library on PyPI
Until you install your own Python library
To import your own module with jupyter
Import your own functions on AWS Glue
Write python modules in fortran using f2py
Publish your own Python library with Homebrew
Try text mining your diary in Python
Module import and exception handling in python
Import Error in Python3: No module named'xxxxx'
Organize python modules and packages in a mess
[Python] Implement your own list-like class using collections.UserList
Email attachments using your gmail account in python.
Summary of how to import files in Python 3
Argument implementation (with code) in your own language
How to define your own target in Sage
Make your own module quickly with setuptools (python)
Build a Python development environment on your Mac
Use Python in your environment from Win Automation
Don't use readlines () in your Python for statement!
Difference in object ID due to import in Python
Import cv2 ModuleNotFoundError: No module named'cv2' in python3
python: Use your own class for numpy ndarray
Quadtree in Python --2
Python in optimization
CURL in python
Metaprogramming in Python
Python 3.3 in Anaconda
Geocoding in python
SendKeys in Python
Meta-analysis in Python
Python module import
Unittest in python
Epoch in Python