【问题标题】:Reading DBF files with pyodbc使用 pyodbc 读取 DBF 文件
【发布时间】:2012-12-21 17:28:56
【问题描述】:

在一个项目中,我需要从 Visual FoxPro 数据库中提取数据,该数据库存储在 dbf 文件中,y 有一个数据目录,其中包含我需要考虑的 539 个文件,每个文件代表一个数据库表,所以我一直在做一些测试,我的代码是这样的:

import pyodbc

connection = pyodbc.connect("Driver={Microsoft Visual FoxPro Driver};SourceType=DBF;SourceDB=P:\\Data;Exclusive=No;Collate=Machine;NULL=No;DELETED=Yes")
tables = connection.cursor().tables()
for _ in tables:
    print _

这仅打印 15 个表,没有明显的模式,总是相同的 15 个表,我认为这是因为其余表是空的,但我检查了列表中的一些表(dbf 文件)是空的同样,我还以为是权限问题,但是所有文件都有相同的权限结构,所以,我不知道这里发生了什么。

有灯吗??

编辑: 它没有截断输出,它列出的表不是第 15 个或类似的表

【问题讨论】:

  • 感谢您的精彩问答!对于任何好奇的人,原始问题中的代码是否适用于 32 位系统上的旧版本 FoxPro。

标签: python database pyodbc dbf


【解决方案1】:

我做到了!!!!

我正在做的事情有几个问题,这里我用我所做的来解决它(在第一次使用 Ethan Furman 的解决方案实施它之后)

首先是驱动问题,原来Windows的DBF驱动是32位程序,运行在64位操作系统上,所以,我安装了Python-amd64,这是第一个问题,所以我安装了 32 位 Python。

第二个问题是库/文件问题,根据this,VFP > 7 中的 dbf 文件不同,所以我的 pyodbc 库无法正确读取它们,所以我尝试了一些 OLE-DB 库但没有成功我决定从头开始。

谷歌搜索了一段时间后,我找到了this 的帖子,终于让我明白了这一点

基本上,我所做的如下:

import win32com.client

conn = win32com.client.Dispatch('ADODB.Connection')
db = 'C:\\Profit\\profit_a\\ARMM'
dsn = 'Provider=VFPOLEDB.1;Data Source=%s' % db
conn.Open(dsn)

cmd = win32com.client.Dispatch('ADODB.Command')
cmd.ActiveConnection = conn
cmd.CommandText = "Select * from factura, reng_fac where factura.fact_num = reng_fac.fact_num AND factura.fact_num = 6099;"

rs, total = cmd.Execute() # This returns a tuple: (<RecordSet>, number_of_records)

while total:
    for x in xrange(rs.Fields.Count):
        print '%s --> %s' % (rs.Fields.item(x).Name, rs.Fields.item(x).Value)
    rs.MoveNext()        #<- Extra indent
    total = total - 1

它给了我 20 条记录,我用 DBFCommander 检查了这些记录并没有问题

首先,您需要安装 pywin32 extensions(32 位)和 Visual FoxPro OLE-DB Provider(仅适用于 32 位),在我的情况下是 VFP 9.0

另外,在 w3c 网站上阅读 de ADO Documentation 也很好

这对我有用。非常感谢回复的人

【讨论】:

  • 恭喜!看起来也是使用 win32 的一个很好的例子。
  • 非常感谢!,是的,这样我可以利用 VFP SQL 的能力,所以我不必实现所有的关系代数,我什至想实现一个无上下文的使用您的 dbf 包和 PLY 语法以“可重用的方式”解决这个问题
  • 这太棒了!我尝试了其他 dbf 库,但似乎它们无法获得正确的输出,可能是因为 VFP 版本不同。如果使用 VFP dbfs,我认为这是首选的解决方案。唯一的缺点是必须为 win32 安装所有东西。
【解决方案2】:

我会使用我自己的dbf package,代码会是这样的:

import dbf
from glob import glob

for dbf_file in glob(r'p:\data\*.dbf'):
    with dbf.Table(dbf_file) as table:
        for record in table:
            do_something_with(record)

一个表是类似列表的,遍历它会返回记录。记录是list-、dict-和obj-like,迭代返回值;除了遍历记录之外,单个字段可以通过偏移量(record[0] 用于第一个字段),通过字段名使用类似字典的访问(record['some_field']),或者通过字段名使用 obj.attr-like访问 (record.some_field)。

如果您只想将每个 dbf 文件的内容转储到 csv 文件中,您可以这样做:

for dbf_file in glob(r'p:\data\*.dbf'):
    with dbf.Table(dbf_file) as table:
        dbf.export(table, dbf_file)

【讨论】:

  • 非常有趣和有用,非常感谢,我喜欢 csv 导出功能,我正在使用其他 dbf 工具对其进行编码。非常感谢你!这为我节省了一些时间。
【解决方案3】:

我知道这并不能直接回答您的问题,但可能仍会有所帮助。我在使用 ODBC 和 VFP 数据库时遇到了很多问题,我发现如果可能的话,将 VFP 表视为空闲表通常要容易得多。

使用 Yusdi Santoso 的 dbf.py 和 glob,这里有一些代码可以打开目录中的每个表并遍历每个记录。

import glob
import os
import dbf

os.chdir("P:\\data")
for file in glob.glob("*.dbf"):
    table = dbf.readDbf(file)
    for row in table:
         #do stuff

【讨论】:

  • 这个还可以,但是你怎么处理这样的数据,怎么选择一些列或者通过外键查找关系?,非常感谢你的回答
  • 如果我没记错的话,数据会出现在字典列表中。 for row in table: data = row['FIELDNAME'] 对于排序,您可以使用运算符来执行table.sort(key=operator.itemgetter('FIELDNAME')) 之类的操作。至于外键,在这种情况下都是手动的。您正在使用此方法处理表级别而不是数据库级别。
  • 非常感谢,我试过了,效果很好。如果我在数据库级别找不到方法,我会这样做。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-12-03
  • 2022-12-10
  • 2012-02-19
  • 1970-01-01
相关资源
最近更新 更多