我怎样才能让 python 的 IfcOpenShell 使用与它读取的文件相同的 unicode 进行写入?

How can i get IfcOpenShell for python to write with the same unicode as the file it reads?

我正在使用 IfcOpenshell 读取 .ifc 文件。进行一些更改,然后将其写入新的 .ifc 文件。但是 IfcOpenshell 编写 unicode 的方式与读取它的方式不同。

我正在创建一个脚本,用于向每个 ifcelement 添加一个具有属性的 pset。这些属性的值是从现有属性中复制的。所以基本上我正在创建一个 pset,将选定的信息收集到一个地方。 在现有值包含 unicode utf-8 之前,这一直很有效。 它被读取和解码以在打印时显示正确的值,但它写入 unicode 的方式与读取它的方式不同。 我尝试更改 PyCharm 中使用的 unicode,但没有成功。我在其他地方找到了类似的帖子,但没有找到解决办法。 从我在其他地方读到的内容来看,它与 unicode encoder/decoder IfcOpenshell 的使用有关,但我不能确定。

def mk_pset():
    global param_name
    global param_type
    global max_row
    global param_map
    wb = load_workbook(b)
    sheet = wb.active
    max_row = sheet.max_row
    max_column = sheet.max_column
    param_name = []
    param_type = []
    param_map=[]
    global pset_name
    pset_name = sheet.cell(row=2, column=1).value
    for pm in range(2, max_row+1):
        param_name.append((sheet.cell(pm, 2)).value)
        param_type.append((sheet.cell(pm, 3)).value)
        param_map.append((sheet.cell(pm,4)).value)
    print(param_type,' - ',len(param_type))
    print(param_name,' - ',len(param_name))
    create_pset()



def create_pset():

    ifcfile = ifcopenshell.open(ifc_loc)
    create_guid = lambda: ifcopenshell.guid.compress(uuid.uuid1().hex)
    owner_history = ifcfile.by_type("IfcOwnerHistory")[0]
    element = ifcfile.by_type("IfcElement")
    sets = ifcfile.by_type("IfcPropertySet")
    list = []
    for sett in sets:
        list.append(sett.Name)
    myset = set(list)
    global antall_parametere
    global index
    index = 0
    antall_parametere = len(param_name)

    if pset_name not in myset:
        property_values = []
        tot_elem = (len(element))
        cur_elem = 1
        for e in element:
            start_time_e=time.time()
            if not e.is_a() == 'IfcOpeningElement':
                type_element.append(e.is_a())
                for rel_e in e.IsDefinedBy:
                    if rel_e.is_a('IfcRelDefinesByProperties'):
                        if not rel_e[5][4] == None:
                            index = 0
                            while index < antall_parametere:
                                try:
                                    ind1 = 0
                                    antall_ind1 = len(rel_e[5][4])
                                    while ind1 < antall_ind1:
                                        if rel_e[5][4][ind1][0] == param_map[index]:
                                            try:
                                                if not rel_e[5][4][ind1][2]==None:
                                                    p_type = rel_e[5][4][ind1][2].is_a()
                                                    p_verdi =rel_e[5][4][ind1][2][0]
                                                    p_t=param_type[index]
                                                    property_values.append(ifcfile.createIfcPropertySingleValue(param_name[index], param_name[index],ifcfile.create_entity(p_type,p_verdi),None),)
                                                    ind1 += 1
                                                else:
                                                    ind1 +=1
                                            except TypeError:
                                                pass
                                                break
                                        else:
                                            ind1 += 1
                                except AttributeError and IndexError:
                                    pass
                                index += 1
                            index = 0
            property_set = ifcfile.createIfcPropertySet(create_guid(), owner_history, pset_name, pset_name,property_values)
            ifcfile.createIfcRelDefinesByProperties(create_guid(), owner_history, None, None, [e], property_set)
            ifc_loc_edit = str(ifc_loc.replace(".ifc", "_Edited.ifc"))
            property_values = []
            print(cur_elem, ' av ', tot_elem, ' elementer ferdig. ',int(tot_elem-cur_elem),'elementer gjenstår. Det tok ',format(time.time()-start_time_e),' sekunder')
            cur_elem += 1
        ifcfile.write(ifc_loc_edit)
    else:
        ###print("Pset finnes")
        sg.PopupError("Pset er allerede oprettet i modell.")

我希望写入的 p_verdi 等于读取的 p_verdi。

原文阅读(D\X2[=38=]F8\X0\r):

#2921= IFCBUILDINGELEMENTPROXYTYPE('3QPADpsq71CHeCe7e3GDm5',#32,'D\X2[=12=]F8\X0\r',$,$,$,$,'DA64A373-DB41-C131-1A0C-A07A0340DC05',$,.NOTDEFINED.);

书面(D\X4[=39=]0000F8\X0\r):

#2921=IFCBUILDINGELEMENTPROXYTYPE('3QPADpsq71CHeCe7e3GDm5',#32,'D\X4[=13=]0000F8\X0\r',$,$,$,$,'DA64A373-DB41-C131-1A0C-A07A0340DC05',$,.NOTDEFINED.);

解码为"Dør"

这也发生在硬间距上:

('2\X2[=14=]A0\X00')

正确打印为:('2 090')

被写入:

('2\X4[=15=]0000A0\X00')

我的 ifc 使用软件无法读取书面表格。

与其说是一个解决方法,不如说是一个答案。

经过更多研究,我发现大多数 IFC 阅读软件似乎不支持 X4 编码,所以我用正则表达式做了一个解决方法。基本上找到所有内容并将 \X4[=17=]00 替换为 \X2。这适用于我迄今为止遇到的所有规范字符。但如前所述,这只是一种可能不适用于所有人的解决方法。

def X4trans_2(target_file,temp_fil):
from re import findall
from os import remove,rename
dec_file = target_file.replace('.ifc', '_dec.ifc')
tempname = target_file
dec_list = []
with open(temp_fil, 'r+') as r,open(dec_file, 'w', encoding='cp1252') as f:
    for line in r:
        findX4 = findall(r'\X4\0000+[\w]+\X0\', str(line))
        if findX4:
            for fx in findX4:
                X4 = str(fx)
                newX = str(fx).replace('\X4\0000', '\X2\')
                line = line.replace(str(X4), newX)  # print ('Fant X4')
        f.writelines(line)
remove(temp_fil)
try:
    remove(target_file)
except FileNotFoundError:
    pass

rename(dec_file,tempname)

基本上是把ifc打开成文本,找到X4替换成X2再写。