使用pyodbc和pandas

时间:2017-01-02 16:44:56

标签: python csv pandas ms-access pyodbc

背景故事: 我从事金融工作(不是开发人员,非常感谢帮助),我的部门目前非常依赖excel和vba来尽可能地自动化我们的任务。该公司刚刚验证了python发行版,我们现在可以使用它,所以我只是想试一试。

挑战: 我的第一个挑战是将CSV文件加载到MSAcess数据库中(因为我们并不是所有人都非常狡猾,只能使用开发工具和数据库,所以需要让每个人都能轻松完成工作)。

我可以在互联网上找到可以放在一起的不同代码的点点滴滴,它可以正常工作,但结果却变成了弗兰肯斯坦。

它在做什么以及为什么:

  1. 将CSV加载到变量
  2. 删除第一行(因为源文件不是真正的CSV,在文件的开头有垃圾行)
  3. 导出到临时驱动器中的CSV(因为无法弄清楚如何从变量加载到panda)
  4. 使用panda将CSV加载到SQLite(因为panda能够推断每列的数据类型)
  5. 导出"创建表"声明变量
  6. 使用pyodbc
  7. 在.mdb文件中创建表
  8. 逐行将数据加载到.mdb表(它非常慢)
  9. TL; 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 个答案:

答案 0 :(得分:2)

MS Access可以直接查询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 Access Table

MS Access Table

注意Access可以推断列类型,例如第一列中的日期。