我无法在Macbook Pro(运行Mac OS X 10.10.5)和python版本2.7.10上导入pyodbc。我使用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

在过去的几个月中,我尝试了几项尝试都没有用,包括自己构建(以及(重新)安装iodbcunixodbc的过程)。

一件奇怪的事情是,我尝试使用的其他python数据库软件包(例如sqlalchemy,pypyodbc等)均出于各种或相似的原因而工作。这使我怀疑我的ODBC驱动程序或库存在一些潜在的问题,但是我不知道如何诊断它。

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

**添加了更多详细信息以回复毛罗的回答。注意,下面的第二次更新改变了事情。 **

这里是我应该包含在原始问题中的更多详细信息。

首先,这是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

我对“地窖”部分感到怀疑,所以我看了毛罗回答中的路径,无论如何,它们似乎都指向地窖(自制吗?):
$ 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

我可以通过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>

但是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

这提供了最多的信息。至少在我的~/.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

我不确定如何解决isql报告的问题,但似乎表明我使用odbc对我的配置有误。不幸的是,很抱歉,我不知道/确切地记得我为实现这种目的所做的事情-我已经认真尝试了数周不停地尝试与此相关的各种事情。

在mauro发表评论后的第二次更新。

我已经取得了一些进步。我重新安装了unixODBC和freeTDS(直接从http://www.unixodbc.org/http://www.freetds.org/而不是使用自制程序),然后,我的odbc_config命令的输出与mauro的输出匹配。

经过一段时间的探索,然后我能够同时获取osqlisql来成功连接到我的SQL Server实例。 (我之前发现失败的原因之一是因为我的组织中的IT部门在LAN上阻止了所有到端口1433的流量。当我像Windows同事一样切换到Wifi时,它起作用了。)进步很大!

但是,当我尝试再次从python中导入pyodbc时,却得到了与开始时完全相同的错误消息。叹。因此,任何其他想法仍将不胜感激!

最佳答案

首先,感谢 @mauro 提出的有益而持久的建议。

经过几个月的脑袋撞墙后,昨晚我终于能够使它工作!

在这里,我概述了一些关键的东西(对我而言),希望这些东西对我和我一样处于困境中的其他人可能有用。

BG。前一段时间(一个多月),我阅读并尝试执行here建议的操作。尽管我不太清楚自己当时尝试的所有操作,但是这导致我开始使用tsql,并且我认为还安装了Homebrew版本的unixODBCfreeTDS

从我问上述问题开始,这里是我尝试过的一些似乎有影响的事情。 (我不确定哪件事最重要,所以我会介绍所有内容。)上面介绍了第1点和第2点,所以我不再赘述。

I.我从他们的项目网站重新安装了unixODBCfreeTDS

二。我发现端口1433在我的LAN上被阻止,因此我切换到了未阻止的WiFi。

这两件事使我能够使isqlosql正常工作。

三,由于类似于动态链接错误的原因,导致pyodbc无法在python中导入。我尝试直接使用/usr/local/lib/libodbc.dylibdl.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

经过一番挖掘,Thie带领我为32位而不是64位的重新编译unixODBC,如下所示:
sudo ./configure CFLAGS="-m32 -arch i386 -O2" LDFLAGS="-m32 -arch i386" CXXFLAGS="-m32 -arch i386"
sudo make
sudo make install

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

IV。不幸的是,如果没有通过dl.open()进行显式加载,导入仍然会失败。这导致我玩了自己的LD_LIBRARY_PATH(如建议的here),但是似乎还没有任何效果。因此,我仍然无法使用dl.open() hack。

此外,它仍然没有起作用,当我尝试连接到数据源时,它与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

请注意,必须使用全局变量_lib1_lib2使其正常工作(我认为是为了保持加载状态)。

在这一点上,事情似乎终于运转良好,可以使用pyodbc了!

在此过程中,我还尝试了其他一些方法,但是我不清楚它们是否有所帮助。
  • 我也尝试在32位模式下编译freeTDS,类似于我对unixODBC所做的操作,但是我不确定是否可行。
  • 我从github存储库下载,构建和安装了pyodbc,而不是使用pip。 (虽然与pip提供的版本相同(3.0.10版)。)
  • 每个注释#10 here,我在darwin源代码下载(如下)中的setup.pypyodbc案例中添加了两行,然后重新运行python.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']
    
  • 完成所有操作后,我进行了检查,并且还可以导入和使用pypyodbc,而无需使用dl.open() hacks。我不确定是否需要上述所有步骤。我怀疑主要问题是库的32位和64位版本。


  • 最后,尽管这与我无法导入pyodbc的原因无关,但我会添加一条注释,说明导致我损失了将近一个小时的事情。在某些时候,我尝试遵循this site上的(非常有帮助)说明。但是,后来我发现作者显示的非DSN连接字符串不起作用。相反,我不得不使用FreeTDS连接属性shown here来使事情工作。例如:
    "DRIVER=FreeTDS;Server=*****;Port=1433;TDS_Version=7.2;Database=*****;UID=*****;PWD=*****"
    

    尽管现在大多数情况下对我来说都是有效的,但我应该提到,对于我的某些查询游标,有时有时也会出现以下错误,但我认为这与以上任何内容都不相关。 (相反,我怀疑连接上存在某种“超时”问题。...)
      ...
        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
    

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

    祝所有必须克服这一切的人祝你好运!

    关于python - 无法在Mac上导入Pyodbc,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/34804404/

    10-12 19:34