【问题标题】:PyODBC Cursor.fetchall() causes python to crash (segfault)PyODBC Cursor.fetchall() 导致 python 崩溃(段错误)
【发布时间】:2012-07-25 20:18:43
【问题描述】:

我在 Windows XP 上使用 Python 2.7。

我有一个简单的 python 脚本,它使用 pyodbc 从 AR 数据库中获取数据,该数据库一直运行良好,直到今天。一旦光标到达特定行,我就会收到段错误。我在 C++ 中有类似的代码,检索结果没有问题,所以我认为这是 pyodbc 的问题。无论哪种方式,我都想“抓住”这个错误。我尝试使用 subprocess 模块,但它似乎不起作用,因为一旦脚本遇到段错误,它就会挂在“python.exe 遇到问题并需要关闭”上。信息。我想我可以设置一些任意的时间框架来完成它,如果没有,则强制关闭该过程,但这似乎有点蹩脚。

我也在这里报告了这个问题 - http://code.google.com/p/pyodbc/issues/detail?id=278

@paulsm4 - 我在下面回答了你的问题,谢谢!

问:您使用的是 Windows/XP(我想是 32 位)、Python 2.7 和 BMC 补救 AR。对吗?

答:是的,在 Win XP 32 位和 Win Server 2008 R2 64 位上失败。

问:您(或者您的客户,如果他们购买了 Remedy AR) 可以通过 BMC 拨打支持电话吗?

A:可能不会……

问:你能找出导致段错误的列吗? “什么是 发生段错误时不同”?

答:只是这一行……​​但我现在已将问题与您的以下建议隔离开来。我使用循环来获取每个字段,直到发生段错误。

cursor.columns(table="mytable")
result = cursor.fetchall()
columns = [x[3] for x in result]
for x in columns:
    print x
    cursor.execute("""select "{0}"
                      from "mytable"
                      where id = 'abc123'""".format(x))
    cursor.fetchall()

一旦我确定了导致段错误的列,我就尝试查询除该列之外的所有列,并且确定它没有问题。

列的数据类型是 CHAR(1024)。我使用 C++ 来获取数据,并注意到该行的列中的字符数是所有其他行中最多的...1023!认为 PyODBC 的 C 代码中可能有一个缓冲区被写入超出其边界。

2) 启用 ODBC 跟踪:http://support.microsoft.com/kb/274551

3) 回传结果(包括失败的日志跟踪)

好的,我已经创建了一个带有 ODBC 跟踪结果的 pastebin - http://pastebin.com/6gt95rB8。为了保护无辜,我屏蔽了一些字符串值。

看起来可能是由于数据截断。

这是否为我们提供了有关如何解决问题的足够信息?我认为这是 PyODBC 中的一个错误,因为直接使用 C ODBC API 可以正常工作。

更新

所以我编译了 PyODBC 进行调试,我收到了一条有趣的消息 -

Run-Time Check Failure #2 - Stack around the variable 'tempBuffer' was corrupted.

虽然我目前不明白,但调用堆栈如下-

pyodbc.pyd!GetDataString(Cursor * cur=0x00e47100, int iCol=0)  Line 410 + 0xf bytes C++
pyodbc.pyd!GetData(Cursor * cur=0x00e47100, int iCol=0)  Line 697 + 0xd bytes   C++
pyodbc.pyd!Cursor_fetch(Cursor * cur=0x00e47100)  Line 1032 + 0xd bytes C++
pyodbc.pyd!Cursor_fetchlist(Cursor * cur=0x00e47100, int max=-1)  Line 1063 + 0x9 bytes C++
pyodbc.pyd!Cursor_fetchall(_object * self=0x00e47100, _object * args=0x00000000)  Line 1142 + 0xb bytes C++

已解决!

通过确保缓冲区有足够的空间来解决问题。

getdata.cpp 330 行

char tempBuffer[1024];

改为

char tempBuffer[1025];

编译并替换了站点包中的旧 pyodbc.pyd 文件,我们都很好!

感谢您的帮助!

【问题讨论】:

  • 嗨 - 我看到你已经在 PyODBC 上发帖并在 SO 上再次尝试。 Q:底层数据库是什么?问:它崩溃在哪一行?它在什么数据项上崩溃?如果删除该行会发生什么?
  • 感谢您的帮助!基础 DB 是 BMC Remedy AR(操作请求)。我不拥有数据库,因此无法进行编辑。这不是特定的行号,而是特定的行。例如,如果我通过它的 PK 查询该行,我会得到一个段错误。如果我过滤掉该行(即where id <> 'abc123'),我不会收到段错误。如果我使用 ODBC 直接在 C++ 中查询数据库,我不会遇到任何问题。
  • 如果你有一种从 C++ 访问数据库的有效方法,你能从那里检查特定的内容吗?那一行的数据有什么明显的问题吗?
  • 没有什么明显的问题,但是我明天会检查你的每一个问题,谢谢!
  • @pyrospade:your other postthis one 之间有很多建议。运气好了吗?有什么新发现吗?

标签: python segmentation-fault pyodbc


【解决方案1】:

问:您使用的是 Windows/XP(我想是 32 位)、Python 2.7BMC Remedy AR。对吗?

问:您(或者您的客户,如果他们购买了 Remedy AR)是否有机会向 BMC 发起支持电话?

问:你能找出导致段错误的列吗?发生段错误时“有什么不同”?

请执行以下操作:

1) 使用 Python/ODBC 尝试不同的“选择 a、b、c”语句,看看是否可以重现问题(独立于您的程序)并隔离特定列(或者,理想情况下,特定列和行! )

2) 启用 ODBC 跟踪: http://support.microsoft.com/kb/274551

3) 回传结果(包括失败的日志跟踪)

4) 如果这不起作用 - 如果您无法获得 BMC 技术支持参与 - 那么计划 B 可能是在 ODBC 库级别进行调试:

【讨论】:

  • 希望您不介意,但我会编辑答案以使其更易于阅读。
  • @pyrospade 请编辑您的问题以提供答案。 (这里是您建议的编辑的链接,以免浪费您的输入:stackoverflow.com/suggested-edits/333611
【解决方案2】:

对于可能收到此错误的任何其他人,请检查返回的数据类型格式。就我而言,这是一个datetime 列。使用select convert(varchar, getdate(), 20) from xxx 或任何convert 格式来获得您想要的结果。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-04-30
    相关资源
    最近更新 更多