Skip to content

Instantly share code, notes, and snippets.

@Bouke
Last active September 22, 2023 17:23
Show Gist options
  • Star 88 You must be signed in to star a gist
  • Fork 25 You must be signed in to fork a gist
  • Save Bouke/10454272 to your computer and use it in GitHub Desktop.
Save Bouke/10454272 to your computer and use it in GitHub Desktop.
Install FreeTDS, unixODBC and pyodbc on OS X

First, install the following libraries:

$ brew install unixodbc
$ brew install freetds --with-unixodbc

FreeTDS should already work now, without configuration:

$ tsql -S [IP or hostname] -U [username] -P [password]
locale is "en_US.UTF-8"
locale charset is "UTF-8"
using default charset "UTF-8"
1> ^D

Onto unixODBC, we need to link to the driver, edit /usr/local/etc/odbcinst.ini:

[FreeTDS]
Description = TD Driver (MSSQL)
Driver = /usr/local/lib/libtdsodbc.so
Setup = /usr/local/lib/libtdsodbc.so
FileUsage = 1

The test command we're using requires configuring a DSN, so edit /usr/local/etc/odbc.ini:

[MYDSN]
Driver = FreeTDS
Server = [IP address]
Port = 1433

The configuration for your DNS might vary, you might need the TDS_Version or Servername directives. The above worked for me for SQL Server 2008 R2. Now, run the test command:

$ isql MYDSN [username] [password] -v
+---------------------------------------+
| Connected!                            |
|                                       |
| sql-statement                         |
| help [tablename]                      |
| quit                                  |
|                                       |
+---------------------------------------+
SQL> ^D

If the test succeeded, you can continue onto installing the Python library pyodbc. Version 3.0.7 and before didn't link with unixODBC, so a change had to be made to setup.py, follow the steps at the bottom instead. The current version (3.0.10) has resolve this issue, so you can go ahead and install from pypi:

pip install pyodbc

Now pyodbc should work:

import pyodbc
pyodbc.connect('DSN=MYDSN;UID=[username];PWD=[password]')

You don't need to have your DSN configured in odbc.ini, so clear that file. You probably want to select a database on connect, so change your connect line to read:

pyodbc.connect('DRIVER=FreeTDS;SERVER=[IP address];PORT=1433;DATABASE=[database];UID=[username];PWD=[password]')

Note that you could also link to the library file of FreeTDS instead of using odbcinst.ini, like this:

pyodbc.connect('DRIVER=/usr/local/lib/libtdsodbc.so;SERVER=[IP address];PORT=1433;DATABASE=[database];UID=[username];PWD=[password]')

Reference -- Installing pyodbc version 3.0.7 and before

Version 3.0.7 didn't link with unixODBC on OS X, so a change had to be made to setup.py. Note that the current version of writing (3.0.10) doesn't have this issue. Follow these steps only to install the old version. Download the source package and extract it somewhere. Find the following lines (146-147):

    elif sys.platform == 'darwin':
        # OS/X now ships with iODBC.

And change this line:

        settings['libraries'].append('iodbc')

into:

        settings['libraries'].append('odbc')

Then run the following command to install:

> python install .
@nightvision04
Copy link

nightvision04 commented Jan 23, 2023

@manamhr I am running into the same problem:

After running the python command pyodbc.connect('DRIVER=FreeTDS;SERVER=localhost;DATABASE=mydb;UID=myuser;PWD=mypassword'), I get the following error. I have linked the driver in the odbc configuration.

'01000', "[01000] [unixODBC][Driver Manager]Can't open lib '/opt/local/lib/libtdsodbc.so' : file not found (0) (SQLDriverConnect)"

I am on a mac m1. I tried using both the macports and brew guides mentioned above.

Here's the output of otool -L /opt/local/lib/libtdsodbc.so:

/opt/local/lib/libtdsodbc.so:
	/opt/local/lib/libodbc.2.dylib (compatibility version 3.0.0, current version 3.0.0)
	/opt/local/lib/libodbcinst.2.dylib (compatibility version 3.0.0, current version 3.0.0)
	/opt/local/lib/libiconv.2.dylib (compatibility version 9.0.0, current version 9.1.0)
	/opt/local/lib/libhogweed.6.dylib (compatibility version 6.0.0, current version 6.6.0)
	/opt/local/lib/libgssapi_krb5.2.2.dylib (compatibility version 2.0.0, current version 2.2.0)
	/opt/local/lib/libgnutls.30.dylib (compatibility version 59.0.0, current version 59.2.0)
	/opt/local/lib/libnettle.8.dylib (compatibility version 8.0.0, current version 8.6.0)
	/opt/local/lib/libgmp.10.dylib (compatibility version 15.0.0, current version 15.1.0)
	/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1319.0.0)

And here is the output of: otool -L /opt/homebrew/lib/libtdsodbc.so

/opt/homebrew/lib/libtdsodbc.so:
	/opt/homebrew/opt/unixodbc/lib/libodbc.2.dylib (compatibility version 3.0.0, current version 3.0.0)
	/opt/homebrew/opt/unixodbc/lib/libodbcinst.2.dylib (compatibility version 3.0.0, current version 3.0.0)
	/usr/lib/libiconv.2.dylib (compatibility version 7.0.0, current version 7.0.0)
	/System/Library/Frameworks/Kerberos.framework/Versions/A/Kerberos (compatibility version 5.0.0, current version 6.0.0)
	/opt/homebrew/opt/openssl@1.1/lib/libssl.1.1.dylib (compatibility version 1.1.0, current version 1.1.0)
	/opt/homebrew/opt/openssl@1.1/lib/libcrypto.1.1.dylib (compatibility version 1.1.0, current version 1.1.0)
	/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1319.0.0)

The contents of my odbcinst.ini configuration in /etc/odbcinst.ini:

[ODBC Driver 18 for SQL Server]
Description=Microsoft ODBC Driver 18 for SQL Server
Driver=/opt/homebrew/lib/libmsodbcsql.18.dylib
UsageCount=1

[ODBC Driver 17 for SQL Server]
Description=Microsoft ODBC Driver 17 for SQL Server
Driver=/opt/homebrew/lib/libmsodbcsql.17.dylib
UsageCount=4

[FreeTDS]
Description=ODBC for FreeTDS
Driver=/opt/homebrew/lib/libtdsodbc.so
Setup=/opt/homebrew/lib/libtdsodbc.so
UsageCount=4

To be clear, I am able to successfully connect to my local sql database from within docker and within tsql. So I just need to point pyodbc to use the same drivers that tsql is using.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment