Having problems with Python, OpenSCAD and solidpython, when trying to use special characters

Hello, so im writing a program to automate making items with names on them, and im encountering a problem when trying to render the models with special characters ž đ š ć č, where it cant translate them i guess and it just ends up crashing. ill post the code here and explain a bit within it.

import pandas as pd
from solid import *
import subprocess
import time




def assembly(annotation1="", full_name="", annotation3=""):
    # Load the STL file and add annotation
    a = import_stl(f"C:\\Users\\Miki\\Desktop\\Blank Key Chain.stl") + rotate([-90, 0, 0])
    
    # Rotate and move the first text with linear extrusion
    rotated_text1 = rotate([-90, 0, 0])(
        translate([2.5, 16.5, 3])(
            linear_extrude(5)(
                text(annotation1,
                     size=5.3,
                     font="helvetica",
                     halign="left",
                     valign="baseline")
            )
        )
    )

    # Rotate and move the second text with linear extrusion
    rotated_text2 = rotate([-90, 0, 0])(
        translate([9, 10, 3])(
            linear_extrude(5)(
                text(full_name,
                     size=5,
                     font="helvetica",
                     halign="left",
                     valign="baseline")
            )
        )
    )

    # Rotate and move the third text with linear extrusion
    rotated_text3 = rotate([-90, 0, 0])(
        translate([2.5, 3, 3])(
            linear_extrude(5)(
                text(annotation3,
                     size=5.3,
                     font="helvetica",
                     halign="left",
                     valign="baseline")
            )
        )
    )
    #print("test1")
    # Subtract the rotated texts from the main object
    value = a - rotated_text1 - rotated_text2 - rotated_text3
    return value

if __name__ == '__main__':
     # Read the Excel file
    
   
    df = pd.read_excel(r"C:\Users\Miki\Desktop\data.xlsx" ,sheet_name='Sheet1')
    #print(df.iterrows)
    num_rows = len(df)
    #print(df)
    #print(df.shape)
    # Iterate through each row of the Excel sheet
    for index, row in df.iterrows():
    # Read values from the first row and first three columns
        annotation1 = row.iloc[2] #1st phone number
        annotation2 = row.iloc[0] #Name
        annotation3 = row.iloc[3] #2nd phone number
        annotation4 = row.iloc[1] #Surname
        full_name = f"{annotation2} {annotation4}"
        #full_name = str(annotation2)+" "+str(annotation4)
        #print(full_name)
        #full_name = full_name.encode("utf-8").decode("utf-8")
      
        #print(annotation1,annotation2,annotation3,annotation4)
        # Generate the assembly
        a = assembly(annotation1,str(full_name), annotation3)
      
        # Output the SCAD file with dynamic name based on annotation1
        scad_file = f"export_{annotation2}.scad"
        scad_file_location = f"C:\\Users\\Miki\\Desktop\\SCADfiles"
        scad_render_to_file(a, scad_file, include_orig_code=False)
    
        #scad_file = f"export{annotation2}.scad"
        #scad_file_path = rf"C:\Users\Miki\Desktop\SCADfiles\{scad_file}"
        #with open(scad_file_path, 'w', encoding='utf-8') as f:
        #    f.write(scad_render_to_file(a, include_orig_code=False))

        ######### Problem ko hočem renderat file ne gre, ker ima "full_name" presledek in ga unicoda ne sprejme. help
        #Problem when i want to render the file, it doesnt let me since the "full name" has restricted character "\t" and doesnt work then i guess xD

        # Run OpenSCAD to export the STL file
        stl_file = f"{annotation2}.stl"
        command = f"openscad -o C:\\Users\\Miki\\Desktop\\STLfiles\\{stl_file} C:\\Users\\Miki\\Desktop\\SCADfiles\\{scad_file}"
        subprocess.run(command, shell=True)
        time.sleep(50)
        print(full_name, "je opravljen.")

This here is the error given back, as you can see it crashes at scad_render_to_file where var a has a var within itself “full_name” that contains a special char.

Traceback (most recent call last):
  File "c:\Users\Miki\Desktop\Model_cut_v3.py", line 87, in <module>
    scad_render_to_file(a, scad_file, include_orig_code=False)
  File "C:\Users\Miki\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.12_qbz5n2kfra8p0\LocalCache\local-packages\Python312\site-packages\solid\solidpython.py", line 518, in scad_render_to_file
    return _write_code_to_file(rendered_string, filepath, out_dir, include_orig_code)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\Miki\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.12_qbz5n2kfra8p0\LocalCache\local-packages\Python312\site-packages\solid\solidpython.py", line 562, in _write_code_to_file
    out_path.write_text(rendered_string)
  File "C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.12_3.12.752.0_x64__qbz5n2kfra8p0\Lib\pathlib.py", line 1048, in write_text
    return f.write(data)
           ^^^^^^^^^^^^^
  File "C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.12_3.12.752.0_x64__qbz5n2kfra8p0\Lib\encodings\cp1252.py", line 19, in encode
    return codecs.charmap_encode(input,self.errors,encoding_table)[0]
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
UnicodeEncodeError: 'charmap' codec can't encode character '\u010d' in position 555: character maps to <undefined>

So i was wondering, how i can fix this. Is there maybe a way to decode it within OpenSCAD?, though i dont know if thats possible.

Well if anyone has any ideas how to fix this, i would really appriciate it.

Have you tried passing the encoding='utf-8' argument to pd.read_excel()?

2 Likes

Strangely enough, I was grappling UniCode in Python last week… it’s a PITA.

I need to accept (possibly corrupted) serial data from a 3d controller (Duet/RRF); and needed to reject all non-printing characters in order to pass the result to a JSON decoder safely.

Here is what I ended up with (requires pySerial].):

import serial
rrf = serial.Serial('/dev/ttyACM0',57600,timeout=0.2)
while True:
    string = ''
    char = b''
    while char not in ['\n','\r']:
        try:
            char = rrf.read(1).decode('ascii')
        except UnicodeDecodeError:
            char = b'?'
        if char:
            if char in bytearray(range(0x20,0x7F)).decode('ascii'):
                string += str(char)
            else:
                break
    print('> ' + string)

Reads from a serial port until either a line end or timeout. Then returns a sanitised string (actually a bytearray in my code)

EDIT: The I fixed the (somewhat buggy) example I originally posted; the updated code above is tested and works.

It’s a ‘pythonic’ way to do this; you wrap the .decode() in a try:except: block so that you can catch and process/reject the unicode as needed.
I realise you are doing something different, but the principle/approach can be the same; eg iterate over a string to replace individual characters.

1 Like

I have a nasty feeling that will fail if the encoding doesn’t map; hence my suggestion above.

But if pd.read_excel() handles the encoding correctly without faulting I think that’s a better solution!

So with the help of a friend who is a programmer, we found a solution. I am amazed, since i was stuck on this problem for almost a week, but within 30 minutes we got to a successful solution.

if __name__ == '__main__':
    # Read the Excel file
    num_completed = 0 #var for keeping track of finished 
   
    df = pd.read_excel(f"{excel_location}" ,sheet_name='Sheet1')
   
    num_rows = len(df)
    #print(len(df)) #check table
    #print(df.shape) #check size of matrix

    # Iterate through each row of the Excel sheet
    for index, row in df.iterrows():
    # Read values from the first row and first three columns
        annotation1 = row.iloc[2] #1st phone number
        annotation2 = row.iloc[0] #Name
        annotation3 = row.iloc[3] #2nd phone number
        annotation4 = row.iloc[1] #Surname
        full_name = f"{annotation2} {annotation4}"
       
        print(annotation2, "'s keychain is being created.")
        
       
        #print(annotation1,annotation2,annotation3,annotation4)

        # Generate the assembly
        model = assembly(annotation1, full_name, annotation3)
      
        # Output the SCAD file with dynamic name based on annotation1
       
        scad_file_location = f"C:\\Users\\Miki\\Desktop\\SCADfiles\\export_{annotation2}.scad"
        with open(scad_file_location, "w", encoding="utf8") as f:
           f.write(scad_render(model))
      
        
        ######### Problem ko hočem renderat file ne gre, v primeru, da ima var "full_name" šumnike, ki niso del CP1252 encodinga, ki ga i guess uporablja ta script, zdej nevem kako bi to spremenil, če sploh lahka, ali pa da se dodajo črke

        # Run OpenSCAD to export the STL file
        stl_file = f"C:\\Users\\Miki\\Desktop\\STLfiles\\{annotation2}.stl"
        command = f"openscad -o {stl_file} {scad_file_location}"
        subprocess.run(command, shell=True)
        time.sleep(30)
        num_completed += 1

        print(annotation2, "'s keychain has finished rendering and has created an stl file.")
        print("Number of completed keychains -", num_completed, "/", num_rows ,".")
        
        print("\n")

The problem was with the solidpython library and not with the pd (panda library)

1 Like

Actually it was with the encoding. This two liner forces the file to utf8 before it is processed as before.

2 Likes