使用Python中的mdbtools从.mdb文件中提取和排序数据

时间:2013-06-15 12:18:34

标签: python database ms-access csv mdbtools

我对Python很陌生,所以任何帮助都会受到赞赏。我试图在Linux上使用mdbtools从2000 .mdb文件中提取和排序数据。到目前为止,我只能获取.mdb文件并将所有表转储到.csv中。由于需要处理大量文件,因此会造成巨大的混乱。

我需要从特定表中提取特定的排序数据。例如,我需要名为“Voltage”的表。该表由多个循环组成,每个循环也有几行。循环通常按时间顺序排列,但在某些情况下,时间戳会延迟记录。像循环一样,第一行可以比循环1第一行具有更晚的时间。我需要根据第一个或最后五个周期的时间提取周期的最新一行。例如,在下表中,我将需要第二行。

Cycle#    Time        Data
  1      100.59        34
  1      101.34        54
  1      98.78         45  
  2      
  2
  2   ........... 

这是我使用的脚本。我正在使用命令python extract.py table_files.mdb.但我希望用./extract.py调用该脚本。文件名的路径应该在脚本本身。

import sys, subprocess, os

DATABASE = sys.argv[1]

subprocess.call(["mdb-schema", DATABASE, "mysql"])

# Get the list of table names with "mdb-tables"
table_names = subprocess.Popen(["mdb-tables", "-1", DATABASE],
                               stdout=subprocess.PIPE).communicate()[0]
tables = table_names.splitlines()

print "BEGIN;" # start a transaction, speeds things up when importing
sys.stdout.flush()

# Dump each table as a CSV file using "mdb-export",
# converting " " in table names to "_" for the CSV filenames.
for table in tables:
    if table != '':
        filename = table.replace(" ","_") + ".csv"
        file = open(filename, 'w')
        print("Dumping " + table)
        contents = subprocess.Popen(["mdb-export", DATABASE, table],
                                    stdout=subprocess.PIPE).communicate()[0]
        file.write(contents)
        file.close()

2 个答案:

答案 0 :(得分:3)

就个人而言,我不会花费大量时间来试图让mdbtoolsunixODBCpyodbc一起工作。正如Pedro在他的评论中所建议的那样,如果你可以让mdb-export将表转储到CSV文件,那么你可以通过将这些CSV文件导入SQLite或MySQL来节省相当多的时间,即比在Linux平台上使用mdbtools更强大。

一些建议:

  1. 考虑到所涉及的.mdb个文件(以及.csv个文件)的数量庞大,您可能希望将CSV数据导入到一个带有附加列的大表中,以指示源文件名。这比2000个单独的表格更容易管理。

  2. 在新数据库中创建目标表时,您可能希望为[时间]列使用decimal(而不是float)数据类型。

  3. 同时,将[Cycle#]列重命名为[Cycle]。列名中的“有趣字符”可能是一种真正的麻烦。

  4. 最后,要为给定[SourceFile]和[Cycle]选择“最后”读数(最大[时间]值),您可以使用如下查询:

    SELECT
        v1.SourceFile, 
        v1.Cycle,
        v1.Time, 
        v1.Data 
    FROM 
        Voltage v1 
        INNER JOIN 
        (
            SELECT
                SourceFile, 
                Cycle, 
                MAX([Time]) AS MaxTime 
            FROM Voltage 
            GROUP BY SourceFile, Cycle
        ) v2 
            ON v1.SourceFile=v2.SourceFile 
               AND v1.Cycle=v2.Cycle 
               AND v1.Time=v2.MaxTime
    

答案 1 :(得分:0)

为了将它直接带到python3中的Pandas,我写了这个小片段

import sys, subprocess, os
from io import StringIO
import pandas as pd
VERBOSE = True
def mdb_to_pandas(database_path):
    subprocess.call(["mdb-schema", database_path, "mysql"])
    # Get the list of table names with "mdb-tables"
    table_names = subprocess.Popen(["mdb-tables", "-1", database_path],
                                   stdout=subprocess.PIPE).communicate()[0]
    tables = table_names.splitlines()
    sys.stdout.flush()
    # Dump each table as a stringio using "mdb-export",
    out_tables = {}
    for rtable in tables:
        table = rtable.decode()
        if VERBOSE: print('running table:',table)
        if table != '':
            if VERBOSE: print("Dumping " + table)
            contents = subprocess.Popen(["mdb-export", database_path, table],
                                        stdout=subprocess.PIPE).communicate()[0]
            temp_io = StringIO(contents.decode())
            print(table, temp_io)
            out_tables[table] = pd.read_csv(temp_io)
    return out_tables