Ускорьте диалект pandas to_sql ms access с помощью sqlalchemy, pyodbc,lxml из XML-файлов

#python #pandas #xml #ms-access #sqlalchemy

Вопрос:

Я хотел бы спросить, я застрял в достижении максимально оптимизированной скорости с помощью этого кода. код автоматически изменяет таблицу, если он обнаружил ошибку во время запроса, пожалуйста, помогите мне провести рефакторинг этого кода для достижения наилучшего результата. В настоящее время обработка 6 файлов занимает 138 секунд, я хочу сократить ее до самых коротких, любые предложения по рефакторингу кодов приветствуются

 import time
import pandas as pd
from sqlalchemy import create_engine
import msaccessdb
import sqlalchemy as sa
import sqlalchemy_access as sa_a
import pyodbc
import re
import urllib

def split_list(alist, wanted_parts=1):
    length = len(alist)
    return [ alist[i*length // wanted_parts: (i 1)*length // wanted_parts] 
             for i in range(wanted_parts) ]
             
def append(df,df_ne,engine,r):
    df = pd.concat([df_ne, df], axis=1)  
    try:    
        df.to_sql(r,con=engine,index=False,if_exists='append')
    except Exception as e:
        state = True
        error_log = e
        while state == True: 
            try:
                error_column = str(error_log).split('name: ')[1].split('.')[0].replace("'","")
                with engine.begin() as conn:
                    conn.execute(sa.text(f"ALTER TABLE [{r}] ADD [{error_column}] VARCHAR(100);"))
                df.to_sql(r,con=engine,index=False,if_exists='append')
                state = False
            except Exception as e:
                error_log = e
                #print(e)
                error_column = str(error_log).split('name: ')[1].split('.')[0].replace("'","")
                state = True

             
def proccess_xml(source):
    #GENERATE ENGINE
    connection_string = (
        r'DRIVER={Microsoft Access Driver (*.mdb, *.accdb)};'
        r'DBQ=C:output_generatedg.accdb;'
    )
    connection_uri = f"access pyodbc:///?odbc_connect={urllib.parse.quote_plus(connection_string)}"   
    engine = create_engine(connection_uri,echo=False)      
                 
    #DF NE 
    xml =open(source,'r').read()
    df_ne = pd.DataFrame([str(re.search('<NENAME.*?>(. ?)</NENAME>*', xml).group().replace("<NENAME>","").replace("</NENAME>",""))],columns = ['NE NAME'])
                 
    #MAIN FUNCTION             
    root = ET.parse(source).getroot()
    for main in root:
        if "syndata" in main.tag:
            for object in main : #object is a class
                df_shit = pd.DataFrame()
                for attribute in object :
                    table_name = ET.QName(attribute).localname
                    for column in attribute:
                        data_value = []
                        data_key = []
                        for value in column:
                            if value.tag is not ET.Comment:
                                column_name = ET.QName(value).localname
                                value_name = value.text    
                                #ITER NESTED 
                                if len(value) != 0:
                                    iter_value = []
                                    iter_key = []
                                    counter_it = 0
                                    for it in value: #'it' is an element parent
                                        for el in it:
                                            if el.tag is not ET.Comment:
                                                iter_value.append(el.text)
                                                iter_key.append(ET.QName(el).localname)
                                            else:
                                                iter_value[-1] =" ".join([str(iter_value[-1])," <",el.text,">"])
                                        counter_it  = 1                
                                    value_name = " ".join([str(list(dict.fromkeys(iter_key)))," : ",str(split_list(iter_value, wanted_parts=counter_it))])  
                                data_key.append(column_name)
                                data_value.append(value_name)
                            else:
                                data_value[-1] = " ".join([str(data_value[-1])," <",value.text,">"])   
                                
                        df = pd.DataFrame([data_value],columns = data_key)
                        df_shit = df_shit.append(df)
                    
                if not df_shit.empty:
                    append(df_shit,df_ne,engine,table_name)

start = time.time()    
#ACCESS GENERATOR
msaccessdb.create(r'C:/_generated/g.accdb')
#MAIN PROCESS
proccess_xml('C:/1/CFGDATA.XML')
proccess_xml('C:/2/CFGDATA.XML')
proccess_xml('C:/3/CFGDATA.XML')
proccess_xml('C:/4/CFGDATA.XML')
proccess_xml('C:/5/CFGDATA.XML')
proccess_xml('C:/6/CFGDATA.XML')
end = time.time()                     
print(' TIME ELAPSED :'   str(end - start))   ```

 

Комментарии:

1. связанные: github.com/gordthompson/sqlalchemy-access/wiki/…

2. @GordThompson спасибо!