【问题标题】:Extract and sort data from .mdb file using mdbtools in Python在 Python 中使用 mdbtools 从 .mdb 文件中提取和排序数据
【发布时间】:2013-06-15 12:18:33
【问题描述】:

我对 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()

【问题讨论】:

  • 我建议将mdb-export 的结果导入SQLite 数据库,然后您可以轻松查询。
  • OP 的上述代码来自okfnlabs.org/handbook/data/patterns/liberating-access-databases,除了在 Python 3 中它工作得很好,因为 Python 3 不像 Python 2 那样使用字节作为默认字符串。对于 Python 3,您必须在带有 communicate()[0] 的行中添加类似 .decode("utf-8") 的内容,例如communicate()[0].decode("utf-8")
  • 要补充一些已经在这里的答案,使用 accdb/mdb 文件是一种 PITA。似乎没有任何东西(例如 Pandas)支持它,至少在 Windows 上没有微软的专有驱动程序或在 linux/unix 上没有像 mdb-tools 这样的第三方库......所以使用 Access 文件的最佳方法是将它们转换为更标准的东西像 CSV 或 SQL 一样,然后进行过滤/排序/转换/等。

标签: python database ms-access csv mdbtools


【解决方案1】:

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

一些建议:

    1234563这将比大约 2000 个单独的表更容易管理。
  1. 在新数据库中创建目标表时,您可能希望对 [Time] 列使用 decimal(而不是 float)数据类型。

  2. 同时,将 [Cycle#] 列重命名为 [Cycle]。列名中的“有趣的字符”可能会很麻烦。

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

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

【讨论】:

  • 天啊,我迷路了。刚接触 Python 和编程通常会让事情看起来过于复杂。基本上我不需要将最终结果导出到新数据库中。我所需要的只是一个排序的 .CSV 文件,我可以轻松访问该文件以生成绘图、执行计算等。
  • 我明白,但我对mdbtools 的体验是,如果幸运的话,它有点 有效,有时。我什至尝试使用您的示例数据在 Linux 中使用 mdbtoolspyodbc 进行快速测试,结果一点也不令人鼓舞。您提出的建议在 Windows 机器上很容易完成(因此避免使用mdbtools),但在 Linux 上却不是那么简单。因此,如果您必须在 Linux 中完成这项工作,您可以(a)使用 Python 自行扫描 CSV 文件,或者(b)将 CSV 文件转储到另一个数据库中,然后从那里排序/选择。
  • 现在我只需要将 .mdb 文件中的一两个表保存到 .csv 中。然后我可以使用 glob 函数或类似函数对这些文件一一排序。我上面使用的代码很好地转储了表格。顺便说一句,我怎样才能在 Windows 机器上做同样的事情?
【解决方案2】:

为了将它直接带到 python3 中的 Pandas,我写了这个小 sn-p

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-03-03
    • 1970-01-01
    • 2012-05-28
    • 2017-11-20
    • 2012-04-04
    • 1970-01-01
    • 1970-01-01
    • 2013-03-13
    相关资源
    最近更新 更多