I need to call some specific Python code which is not easy to implement as Godot code and came up with this solution. Note that the essence of the script is that the Python code generates a dictionary with the required information and prints this as a JSON formatted string. Godot calls the script and receives the output and uses the internal JSON functionality to convert the string to a Godot JSON object. Also note that the Python script gets called from the python version that is set in the environment specific for this Python code (python-venv).
Not too difficult actually!
import sys
import json
from leveelogic.soilinvestigation.cpt import Cpt, CptConversionMethod
from leveelogic.soil.soilcollection import SoilCollection
import logging
logging.basicConfig(
filename="read_cpts.log",
filemode="a+",
format="%(asctime)s %(levelname)s %(message)s",
datefmt="%H:%M:%S",
level=logging.INFO,
)
def read_cpts(filenames):
result = {"cpts": [], "soils": []}
# add soil colors
sc = SoilCollection()
for soil in sc.soils:
result["soils"].append({"code": soil.code, "color": soil.color})
# add soillayers per cpt
for filename in filenames:
try:
cpt = Cpt.from_file(filename)
sp1d = cpt.to_soilprofile1(
minimum_layerheight=0.5,
cptconversionmethod=CptConversionMethod.ROBERTSON,
peat_friction_ratio=5.0,
)
cpt_dict = {
"name": cpt.name,
"x": cpt.x,
"y": cpt.y,
"top": cpt.top,
"soillayers": [],
}
for soillayer in sp1d.soillayers:
cpt_dict["soillayers"].append(
{
"top": soillayer.top,
"bottom": soillayer.bottom,
"code": soillayer.soilcode,
}
)
result["cpts"].append(cpt_dict)
except Exception as e:
logging.error(f"Got error, {e}")
continue
return result
if __name__ == "__main__":
result = read_cpts(sys.argv[1:])
print(json.dumps(result))
Note that I have a simple 2D scene with a button and a FileDialog.
func _on_btn_add_cpts_pressed():
$dlg_select_file.popup()
func _on_dlg_select_file_files_selected(paths):
var output = []
var args = ["Z:/Python/godot/read_cpts.py"]
args.append_array(paths)
OS.execute("Z:/Python/godot/.venv/Scripts/python.exe", args, output)
var data = JSON.parse_string(output[0])
print(data) # or do what you want with the new data object!