2017-01-02 2 views
0

Фоновая история: Я работаю по финансам (не разработчик, так что помощь очень ценится), мой отдел в настоящее время в значительной степени зависит от первенствует и VBA для автоматизации в максимально возможной степени наши задачи. Компания просто проверила дистрибутив python, и теперь нам разрешено использовать его, поэтому я просто подумал о том, чтобы попробовать.нагрузки CSV для .mdb с помощью pyodbc и панд

Задача: Моя первая задача была, чтобы загрузить CSV-файла в базу данных MSAcess (потому что не все из нас технологий Сави достаточно для работы исключительно с помощью средства разработки и БД, так что нужно, чтобы сделать вещи легко для всех) ,

Я мог бы найти кусочки разных кода ppl в Интернете, которые я мог бы собрать вместе, это работает, но, оказывается, это стало Frankenstein.

Что он делает и почему:

  1. Загрузить CSV в переменную
  2. Strip из первых строк (потому что исходный файл не НАСТОЯЩИЙ CSV, есть мусорные строки в начале файла)
  3. Экспорт в CSV в темпе диске (потому что не мог понять, как загрузить с пандой из переменных)
  4. загрузить CSV в SQLite с помощью панды (потому что панды способны выводить тип данных каждого столбца)
  5. Экспорт "создать таблицу" заявление переменной
  6. Создать таблицу в .mdb файле с помощью pyodbc
  7. Загрузить данные в .mdb таблицы по строкам (это очень медленно)

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

Задайте это по адресу http://codereview.stackexchange.com/ – Gustav

+0

Доступ также может вызывать типы столбцов. Вы используете для этого панды, потому что это делает лучшую работу, или просто потому, что это то, что вы нашли во время поиска? –

+0

@GordThompson Потому что это то, что я мог найти во время поиска, который не требовал сделать это от Access или даже открыть его. Мой план состоял в том, чтобы иметь функцию, которая могла бы анализировать различные CSV-файлы и загружать их в .mdb, без необходимости делать это из Access, поэтому у меня мог бы быть сценарий, который запускается автоматически в течение ночи, а позже, возможно, улучшится, прочитав из таблицу со списком файлов csv и соответствующее .mdb и имя таблицы. Код выше kinda работает, но он медленный, особенно последняя часть, где он запускает запрос вставки для каждой строки. – ddensa

ответ

1

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

Clean CSV

Clean CSV

MS Access Таблица

MS Access Table

Примечание Доступ может вывести типы столбцов, такие как дата в первом столбце.

+0

Awsome! Благодаря! – ddensa

Смежные вопросы