2017-01-02 1 views
0

이야기 배경 : 나는 금융 작업 (안 개발자, 그래서 도움이 매우 감사합니다) , 내 부서가 현재의 최대한 자동화 엑셀 및 VBA에 크게 의존 우리의 임무. 이 회사는 파이썬 배포판을 검증했고 이제는 사용할 수있게되었으므로 방금 시도해 보았습니다.로드 CSV는 pyodbc와 팬더를 사용하여 .MDB하는

과제 : 내 첫 번째 과제는 CSV는 MSAcess 데이터베이스에 파일을로드 할 수 있었다 (아니 우리 모두가 충분히 개발 도구 및 데시벨을 사용하여 순수하게 작동, 그래서 모두를 위해 일을 쉽게하기 위해 필요에 기술 Savy은이기 때문에) .

내가 인터넷에 둘러 볼 수있는 여러 가지 ppl 코드의 조각을 발견 할 수는 있지만 작동하고 있지만 그것이 Frankenstein이되었다는 것을 알 수 있습니다. 이 일을 무슨

이유 :

  1. 로드 CSV 변수
  2. 지구 밖으로 첫번째 행에
  3. (소스 파일이 정말를 CSV 아니기 때문에, 파일의 시작에서 쓰레기 행이)
  4. 임시 드라이브의 CSV로 내보내기
  5. 팬더를 사용하여 SQLite에 CSV로드 (팬더가 각 열의 데이터 유형을 추론 할 수 있기 때문에)
  6. 수출

TL (매우 느린) 행에 의해 테이블 ​​행을 .MDB 할 pyodbc에게

  • 로드 데이터를 사용하여 .MDB 파일에 테이블을 만들고 변수
  • 에 문 "테이블을 만듭니다"; DR :
    현재 코드는 다른 코드의 패치 워크이며,보기 흉하고 느립니다. 더 효율적으로 만들거나 최적화하려면 어떻게해야합니까?

    목표는 올바른 데이터 형식을 사용하여 CSV를 .mdb로로드하는 코드를 만드는 것입니다.

    import csv 
    import pyodbc 
    import pandas 
    import pandas.io.sql 
    import sqlite3 
    import tempfile 
    import time 
    import string 
    
    
    def load_csv_to_access(access_path, table_name, csv_path, skip_rows): 
    
    
    # open CSV file, load to a variable, output to a temp file excluding first non csv rows 
    # 
    filename = csv_path 
    csv_file = open(filename) 
    txt = "" 
    for index, line in enumerate(csv_file, start=0): #Skip first rows 
        if index > skip_rows: 
         txt += line 
    csv_file.close() 
    temp_filename = time.strftime("%y%m%d%H%M%S") + '.csv' 
    temp_filepath = tempfile.gettempdir() + '\\' + temp_filename 
    file = open(temp_filepath, 'w+') 
    file.write(txt) # create temp csv 
    file.close() 
    print "1: temp file created: " + temp_filepath 
    
    # Use panda and SQLite to infer data type of CSV fields 
    # 
    df = pandas.read_csv(temp_filepath, delimiter=';', index_col=0, engine='python') 
    df.columns = df.columns.str.replace(' ', '_') 
    # connect to in-memory database for testing; replace `:memory:` w/ file path 
    con = sqlite3.connect('db.sqlite') 
    df.to_sql(table_name, con, if_exists='replace') 
    sqlite_query_string = "SELECT sql FROM sqlite_master where name = '" + table_name + "'" 
    create_table_tuple = con.execute(sqlite_query_string).fetchone() 
    con.close() 
    create_table_string = create_table_tuple[0] 
    print "2: Data type inferred" 
    
    #Connect to AccessDB and load temp CSV 
    # 
    access_string = "DRIVER={Microsoft Access Driver (*.mdb, *.accdb)};DBQ=" + access_path + "; Provider=MSDASQL;" 
    print access_string 
    con = pyodbc.connect(access_string) 
    cur = con.cursor() 
    cur.execute(create_table_string) 
    con.commit() 
    print "3: MS Access table created: " + table_name 
    
    print "4: Loading data rows:" 
    with open(temp_filepath, 'r') as f: 
        reader = csv.reader(f, delimiter=';') 
        columns = next(reader) 
        query = "insert into " + table_name + "({0}) values ({1})" 
        query = query.format(','.join(columns).replace(' ', '_'), ','.join(
         '?' * len(columns))) #Create insert query (replace empty space by underscore to avoid db issues) 
        for index, data in enumerate(reader, start=0): 
         cur.execute(query, data) #Insert row by row 
         print index # For debugging 
        cur.commit() 
    con.close() 
    

    감사합니다. 여러분 모두 저보다 훨씬 낫습니다.

  • +1

    http://codereview.stackexchange.com/ – Gustav

    +0

    에서 액세스 권한을 요청할 수 있습니다. 액세스도 열 형식을 유추 할 수 있습니다. 더 나은 일을하기 때문에 팬더를 사용하고 있습니까? 아니면 검색하는 동안 발견 한 것이기 때문에 팬더를 사용하고 계십니까? –

    +0

    @GordThompson 그게 내가 Access에서 그것을 할 필요가 없거나 심지어 열어 검색하는 동안 찾을 수 있기 때문에. 내 계획은 다른 CSV 파일을 구문 분석하고 Access에서 수행하지 않고 .mdb에로드 할 수있는 기능을 갖추어 야간에 자동으로 실행되는 스크립트를 가질 수 있었으며 나중에 읽기에서 향상시킬 수있었습니다. csv 파일 목록과 해당 .mdb 및 테이블 이름 목록이있는 테이블입니다. 다소 위의 코드가 작동하지만 속도가 느립니다. 특히 각 행에 대한 삽입 쿼리를 실행하는 마지막 부분입니다. – ddensa

    답변

    1

    MS 액세스는 CSV 파일을 직접 쿼리하고 Make-Table Query을 실행하여 결과 테이블을 생성 할 수 있습니다. 그러나 쓰레기 행을 제거하려면 일부 청소가 필요합니다. 아래는 읽기 용과 쓰기 용의 두 파일을 엽니 다.가정 쓰레기는 CSV의 첫번째 컬럼에 상기 if 로직 번째 열의 일부 데이터가 어떤 라인에 기록 (필요에 따라 조정)

    import os 
    import csv 
    import pyodbc 
    
    # TEXT FILE CLEAN 
    with open('C:\Path\To\Raw.csv', 'r') as reader, open('C:\Path\To\Clean.csv', 'w') as writer: 
        read_csv = csv.reader(reader); write_csv = csv.writer(writer, lineterminator='\n') 
    
        for line in read_csv: 
         if len(line[1]) > 0:    
          write_csv.writerow(line) 
    
    # DATABASE CONNECTION 
    access_path = "C:\Path\To\Access\\DB.mdb" 
    con = pyodbc.connect("DRIVER={{Microsoft Access Driver (*.mdb, *.accdb)}};DBQ={};" \ 
            .format(access_path)) 
    
    # RUN QUERY 
    strSQL = "SELECT * INTO [TableName] FROM [text;HDR=Yes;FMT=Delimited(,);" + \ 
         "Database=C:\Path\To\Folder].Clean.csv;"  
    cur = con.cursor() 
    cur.execute(strSQL) 
    con.commit() 
    
    con.close()       # CLOSE CONNECTION 
    os.remove('C\Path\To\Clean.csv')  # DELETE CLEAN TEMP 
    

    원시 CSV를

    Raw CSV File

    면도 CSV

    Clean CSV

    ,

    MS 액세스 테이블

    MS Access Table

    공지 통로는 첫 번째 열의 일로 열 유형을 추론 할 수있다.

    +0

    굉장! 감사! – ddensa