我在 Windows XP 上使用 Python 2.7。
我有一个简单的 python 脚本,它使用 pyodbc 从 AR 数据库中获取数据,直到今天它一直运行良好。一旦光标到达特定行,我就会收到段错误。我在 C++ 中有类似的代码,检索结果没有问题,所以我认为这是 pyodbc 的问题。无论哪种方式,我都想“捕获”这个错误。我试过使用 subprocess 模块,但它似乎不起作用,因为一旦脚本遇到段错误,它就会卡在“python.exe 遇到问题需要关闭”上。信息。我想我可以为它设置一些任意的时间框架来完成,如果没有,则强制关闭该过程,但这似乎有些蹩脚。
我也在这里报告了这个问题 - http://code.google.com/p/pyodbc/issues/detail?id=278
@paulsm4 - 我已经在下面回答了你的问题,谢谢!
Q: You're on Windows/XP (32-bit, I imagine), Python 2.7, and BMC Remedy AR. Correct?
答:是的,它在 Win XP 32 位和 Win Server 2008 R2 64 位上失败。
Q: Is there any chance you (or perhaps your client, if they purchased Remedy AR) can open a support call with BMC?
答:应该不会吧
Q: Can you isolate which column causes the segfault? "What's different" when the segfault occurs?
答:只是这一行……但我现在已经将问题与您在下面的建议隔离开来。我使用循环来获取每个字段,直到发生段错误。
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) Enable ODBC tracing: http://support.microsoft.com/kb/274551
3) Post back the results (including the log trace of the failure)
好的,我已经用 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 文件,我们都很好!
感谢您的帮助!
最佳答案
问:您使用的是 Windows/XP(我想是 32 位),Python 2.7 , 和 BMC Remedy AR .正确吗?
问:您(或者您的客户,如果他们购买了 Remedy AR)是否有机会向 BMC 调用支持电话?
问:你能找出导致段错误的列吗?发生段错误时“有什么不同”?
请执行以下操作:
1) 使用 Python/ODBC 尝试不同的“select a,b,c”语句,看看您是否可以重现问题(独立于您的程序)并隔离特定列(或者,理想情况下,特定列和行! )
2) 启用 ODBC 跟踪: http://support.microsoft.com/kb/274551
3) 回传结果(包括失败的日志跟踪)
4) 如果这不起作用 - 如果您不能让 BMC 技术支持参与进来 - 那么计划 B 可能是在 ODBC 库级别进行调试:
How to debug C extensions for Python on Windows
问:哪种 C/C++ 编译器最适合您?
关于python - PyODBC Cursor.fetchall() 导致 python 崩溃(segfault),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11657958/