无法在Mac上导入pyodbc

Tur*_*rix 8 python macos odbc pyodbc python-2.7

我无法导入pyodbc我的Macbook Pro(运行Mac OS X 10.10.5)和python版本2.7.10.我曾经pip得到它,我有最新版本(3.0.10).它给了我以下错误:

$ python
Python 2.7.10 (default, Jul 14 2015, 19:46:27) 
[GCC 4.2.1 Compatible Apple LLVM 6.0 (clang-600.0.39)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import pyodbc
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ImportError: dlopen(/Library/Python/2.7/site-packages/pyodbc.so, 2): Symbol not found: _SQLAllocHandle
  Referenced from: /Library/Python/2.7/site-packages/pyodbc.so
  Expected in: flat namespace
 in /Library/Python/2.7/site-packages/pyodbc.so
Run Code Online (Sandbox Code Playgroud)

我在过去的几个月里尝试了几件事无济于事,包括自己构建(以及(重新)安装iodbcunixodbc沿途).

其中一个奇怪的事情是我尝试使用的其他python数据库包(例如sqlalchemy,pypyodbc等)也没有出于各种原因和类似原因.这让我怀疑我的ODBC驱动程序或库有一些潜在的问题,但我不知道如何诊断它.

我正在共享代码环境中工作,团队的其他成员pyodbc通过Windows 使用,我现在真的需要这个.任何帮助或建议将不胜感激!


**在回复mauro的答案时添加了更多详细信息.注意,下面的第二次更新改变了一些**

以下是我应该包含在原始问题中的更多细节.

首先,这是mauro在我的机器上询问的命令的结果.

$ odbc_config --version
2.3.2
$ odbc_config --libs
-L/usr/local/Cellar/unixodbc/2.3.2_1/lib -lodbc
$ odbc_config --odbcini
/usr/local/Cellar/unixodbc/2.3.2_1/etc/odbc.ini
$ odbc_config --odbcinstini
/usr/local/Cellar/unixodbc/2.3.2_1/etc/odbcinst.ini
Run Code Online (Sandbox Code Playgroud)

我对"Cellar"部分持怀疑态度,所以我看着mauro的回答中的路径,他们似乎都指向Cellar(自制?)无论如何:

$ ls -al /usr/local/etc/*odbc*
lrwxr-xr-x  1 *****  admin  39 17 Aug 16:57 /usr/local/etc/odbc.ini@ -> ../Cellar/unixodbc/2.3.2_1/etc/odbc.ini
lrwxr-xr-x  1 *****  admin  43 17 Aug 16:57 /usr/local/etc/odbcinst.ini@ -> ../Cellar/unixodbc/2.3.2_1/etc/odbcinst.ini

$ ls -al /usr/local/etc/odbc*
lrwxr-xr-x  1 *****  admin  39 17 Aug 16:57 /usr/local/etc/odbc.ini@ -> ../Cellar/unixodbc/2.3.2_1/etc/odbc.ini
lrwxr-xr-x  1 *****  admin  43 17 Aug 16:57 /usr/local/etc/odbcinst.ini@ -> ../Cellar/unixodbc/2.3.2_1/etc/odbcinst.ini
1395:Stephens-BlueDot-MacBook-Pro:~/BlueDot/Code/Data Processing Tools} ls -al /usr/local/etc/*odbc*
lrwxr-xr-x  1 *****  admin  39 17 Aug 16:57 /usr/local/etc/odbc.ini@ -> ../Cellar/unixodbc/2.3.2_1/etc/odbc.ini
lrwxr-xr-x  1 *****  admin  43 17 Aug 16:57 /usr/local/etc/odbcinst.ini@ -> ../Cellar/unixodbc/2.3.2_1/etc/odbcinst.ini
1396:Stephens-BlueDot-MacBook-Pro:~/BlueDot/Code/Data Processing Tools} ls -al /usr/local/lib/*odbc*
lrwxr-xr-x  1 *****  admin  46 17 Aug 16:57 /usr/local/lib/libodbc.2.dylib@ -> ../Cellar/unixodbc/2.3.2_1/lib/libodbc.2.dylib
lrwxr-xr-x  1 *****  admin  44 17 Aug 16:57 /usr/local/lib/libodbc.dylib@ -> ../Cellar/unixodbc/2.3.2_1/lib/libodbc.dylib
lrwxr-xr-x  1 *****  admin  48 17 Aug 16:57 /usr/local/lib/libodbccr.2.dylib@ -> ../Cellar/unixodbc/2.3.2_1/lib/libodbccr.2.dylib
lrwxr-xr-x  1 *****  admin  46 17 Aug 16:57 /usr/local/lib/libodbccr.dylib@ -> ../Cellar/unixodbc/2.3.2_1/lib/libodbccr.dylib
lrwxr-xr-x  1 *****  admin  50 17 Aug 16:57 /usr/local/lib/libodbcinst.2.dylib@ -> ../Cellar/unixodbc/2.3.2_1/lib/libodbcinst.2.dylib
lrwxr-xr-x  1 *****  admin  48 17 Aug 16:57 /usr/local/lib/libodbcinst.dylib@ -> ../Cellar/unixodbc/2.3.2_1/lib/libodbcinst.dylib
lrwxr-xr-x  1 *****  admin  45 17 Aug 16:59 /usr/local/lib/libtdsodbc.0.so@ -> ../Cellar/freetds/0.95.18/lib/libtdsodbc.0.so
lrwxr-xr-x  1 *****  admin  42 17 Aug 16:59 /usr/local/lib/libtdsodbc.a@ -> ../Cellar/freetds/0.95.18/lib/libtdsodbc.a
lrwxr-xr-x  1 *****  admin  43 17 Aug 16:59 /usr/local/lib/libtdsodbc.so@ -> ../Cellar/freetds/0.95.18/lib/libtdsodbc.so

/usr/local/lib/tdbcodbc1.0.0:
total 144
drwxr-xr-x   5 root  wheel    170 29 Mar  2013 ./
drwxrwxr-x  44 root  admin   1496 17 Aug 16:59 ../
-rwxr-xr-x   1 root  wheel  49796 29 Mar  2013 libtdbcodbc1.0.0.dylib*
-r--r--r--   1 root  wheel    245 29 Mar  2013 pkgIndex.tcl
-r--r--r--   1 root  wheel  15624 29 Mar  2013 tdbcodbc.tcl
Run Code Online (Sandbox Code Playgroud)

我可以通过tsql(特定的匿名)连接到DNS !

$ tsql -S servername.myserver.com -U me -P mypw -D testdb
locale is "en_CA.UTF-8"
locale charset is "UTF-8"
using default charset "UTF-8"
Setting testdb as default database in login packet
1> 
Run Code Online (Sandbox Code Playgroud)

osqlisql这两个产生问题:

$ isql -v MyDSN me mypw
[S1000][unixODBC][FreeTDS][SQL Server]Unable to connect to data source
[01000][unixODBC][FreeTDS][SQL Server]Unknown host machine name.
[ISQL]ERROR: Could not SQLConnect
Run Code Online (Sandbox Code Playgroud)

这个提供了最多的信息.它~/.odbc.ini至少在我的文件中找到了DSN条目.

$ osql -S MyDSN -U ***** -P ***** 
checking shared odbc libraries linked to isql for default directories...
/usr/local/bin/osql: line 53: ldd: command not found
error: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/strings: can't open file:  (No such file or directory)
osql: problem: no potential directory strings in "/usr/local/bin/isql"
osql: advice: use "osql -I DIR" where DIR unixODBC\'s install prefix e.g. /usr/local
isql strings are:
checking odbc.ini files
    reading /Users/*****/.odbc.ini
[MyDSN] found in /Users/*****/.odbc.ini
found this section:
    [MyDSN]                                                                                                                
    Description         = testdb SQLServer DB
    Driver              = FreeTDS
    Trace               = Yes
    TraceFile           = /tmp/sql.log
    Database            = Places
    ServerName          = *****
    UserName            = *****
    Password            = *****
    Port                = 1433
    Protocol            = 7.2
    ReadOnly            = No
    RowVersioning       = No
    ShowSystemTables    = No
    ShowOidColumn       = No
    FakeOidIndex        = No
looking for driver for DSN [*****] in /Users/*****/.odbc.ini
  found driver line: "  Driver              = FreeTDS"
  driver "FreeTDS" found for [*****] in .odbc.ini
found driver named "FreeTDS"
"FreeTDS" is not an executable file
looking for entry named [FreeTDS] in /odbcinst.ini
grep: /odbcinst.ini: No such file or directory
Run Code Online (Sandbox Code Playgroud)

我不确定如何解决isql报告的问题,但似乎表明我有一些错误配置给我的odbc.不幸的是,我很抱歉我不知道/记得我采取了这样做的确切方法 - 我已经认真地尝试了几周与之相关的各种事情.


毛罗评论后的第二次更新.

我取得了一些进展.我重新安装了unixODBC和freeTDS(直接来自http://www.unixodbc.org/http://www.freetds.org/,而不是使用自制软件),在这样做后,我的odbc_config命令输出与mauro的输出相匹配.

在玩了一些我的路径之后,我就能够获得两者osqlisql成功连接到我的SQL Server实例.(我发现之前失败的原因之一是因为我的组织中的IT部门在局域网上阻止了到端口1433的所有流量.当我切换到Wifi时,就像我的Windows同事一样,它起作用了.)我认为这个进步很大!

但是,当我尝试再次从python中导入pyodbc时,我得到了与我开始时完全相同的错误消息.叹.所以任何其他想法仍然会受到赞赏!

Tur*_*rix 4

首先,感谢@mauro提供的有用且坚持不懈的建议。

经过几个月的头撞墙后,昨晚我终于能够让它发挥作用了!

在这里,我概述了一些(对我来说)关键的事情,希望这些对那些和我有同样困境的人有用。

BG。不久前(一个多月),我阅读并尝试执行此处建议的操作。虽然我不太清楚当时我尝试过的每件事,但这引导我开始tsql工作,而且我认为,我还安装了 HomebrewunixODBC版本freeTDS

从我提出上面的问题开始,以下是我尝试过的一些似乎产生了影响的事情。(我不确定哪些事情是最重要的,所以我把所有的事情都包括了。)第1点和第2点已经在上面描述了,所以我不再赘述。

I. 我重新安装了unixODBC他们freeTDS的项目网站。

二. 我发现我的 LAN 上的端口 1433 被阻止,因此我切换到没有被阻止的 WiFi。

这两件事使我能够isql上班 osql

三.推断pyodbc由于类似于动态链接错误的原因,无法在 python 中导入。我尝试使用和 /usr/local/lib/libodbc.dylib直接加载。在这两种情况下,我都收到错误消息:dl.open()ctype.cdll.LoadLibrary()

dl.error: dlopen(libodbc.dylib, 6): no suitable image found.  Did find:
    /usr/local/lib/libodbc.dylib: mach-o, but wrong architecture
Run Code Online (Sandbox Code Playgroud)

经过一番挖掘后,他引导我重新编译unixODBC32 位而不是 64 位,如下所示:

sudo ./configure CFLAGS="-m32 -arch i386 -O2" LDFLAGS="-m32 -arch i386" CXXFLAGS="-m32 -arch i386"
sudo make 
sudo make install
Run Code Online (Sandbox Code Playgroud)

那时,我能够显式加载libodbc.dylib使用dl.open()最终导入 pyodbc!

四.不幸的是,如果没有显式加载 via dl.open(),导入仍然失败。这导致我开始玩我的LD_LIBRARY_PATH(如此处建议的,但似乎还没有任何效果。所以我仍然坚持使用dl.open()黑客。

此外,它仍然无法工作,freeTDS当我尝试连接到数据源时,与驱动程序相关的失败。这最终让我想到了以下“有效”的破解方法:

import sys
if (sys.platform == 'darwin'):
    import dl
    _lib1 = dl.open("libodbc.dylib")                      # Found in /usr/local/lib
    _lib2 = dl.open("/opt/local/lib/libtdsodbc.so")
import pyodbc
Run Code Online (Sandbox Code Playgroud)

请注意,有必要使用全局变量_lib1_lib2使其正常工作(我认为是为了保持加载的内容)。

至此,一切似乎终于运行良好,我可以使用了pyodbc


在此过程中我还尝试了一些其他方法,但我不清楚它们是否有帮助。

  • 我还尝试freeTDS以 32 位模式进行编译,类似于我所做的unixODBC,但我不确定这是否有效。

  • 我从 github 存储库下载、构建和安装,pyodbc而不是使用pip. (不过,它是相同的版本——3.0.10——作为pip供应品。)

  • 根据此处的评论#10 ,我在源下载(如下)darwin的情况下添加了两行并重新运行。setup.pypyodbcpython.py setup.py build install

喜欢:

elif sys.platform == 'darwin':                                                                                        
    # The latest versions of OS X no longer ship with iodbc.  Assume
    # unixODBC for now.
    settings['libraries'].append('odbc')
    settings['include_dirs'] = ['/opt/local/include']              # Added this line
    settings['library_dirs'] = ['/opt/local/lib']                  # Added this line

    # Python functions take a lot of 'char *' that really should be const.  gcc complains about this *a lot*
    settings['extra_compile_args'].extend([
        '-Wno-write-strings',
        '-Wno-deprecated-declarations'
    ])

    # Apple has decided they won't maintain the iODBC system in OS/X and has added deprecation warnings in 10.8.
    # For now target 10.7 to eliminate the warnings.
    settings['define_macros'].append( ('MAC_OS_X_VERSION_10_7',) )

    settings['include_dirs'] = ['/opt/local/include']
    settings['library_dirs'] = ['/opt/local/lib']
Run Code Online (Sandbox Code Playgroud)
  • 全部完成后,我检查了一下,我也能够pypyodbc 在不使用dl.open()hacks 的情况下导入和使用。我不确定是否需要执行上述所有步骤才能实现这一点。我怀疑主要问题是库的 32 位版本与 64 位版本。

最后,虽然这与我无法导入的原因无关pyodbc,但我会添加一个关于导致我损失近一个小时的事情的注释。在某些时候,我试图遵循此站点上的(非常有用的)说明。然而,我后来发现作者展示的非DSN连接字符串不起作用。相反,我必须使用此处显示的FreeTDS 连接属性才能正常工作。例如:

"DRIVER=FreeTDS;Server=*****;Port=1433;TDS_Version=7.2;Database=*****;UID=*****;PWD=*****"
Run Code Online (Sandbox Code Playgroud)

尽管现在大部分情况都对我有用,但我应该提到,对于我的某些查询游标,我现在有时也会遇到以下错误,但我认为它与上述任何内容都无关。(相反,我怀疑连接上存在某种“超时”问题。...)

  ...
    for row in cursor:
  File "/Library/Python/2.7/site-packages/pypyodbc.py", line 1920, in next
    row = self.fetchone()
  File "/Library/Python/2.7/site-packages/pypyodbc.py", line 1914, in fetchone
    check_success(self, ret)
  File "/Library/Python/2.7/site-packages/pypyodbc.py", line 986, in check_success
    ctrl_err(SQL_HANDLE_STMT, ODBC_obj.stmt_h, ret, ODBC_obj.ansi)
  File "/Library/Python/2.7/site-packages/pypyodbc.py", line 966, in ctrl_err
    raise DatabaseError(state,err_text)
pypyodbc.DatabaseError: (u'08S01', u'[08S01] [FreeTDS][SQL Server]Bad token from the server: Datastream processing out of sync')
Exception pypyodbc.DatabaseError: DatabaseError(u'08S01', u'[08S01] [FreeTDS][SQL Server]Write to the server failed') in <bound method Connection.__del__ of <pypyodbc.Connection instance at 0x60d5a8>> ignored
Run Code Online (Sandbox Code Playgroud)

总而言之,我认为至少有 3 个(如果不是 4 个)原因导致我无法pyodbc在 python 中使用。unixODBC主要的两个与 32 位与 64 位编译以及一些我仍然不太理解的库导入路径问题有关。

祝其他必须努力完成这一切的人好运!