Python, SQLAlchemy, pyodbc and MSSQL on Mac OSX

Update: It has been pointed out to me that I should set the ODBCINI and ODBCSYSINI to point to somewhere more consistent (eg. /usr/local/etc) from wherever is running the python. So in my shell .zshrc, or in the Apache conf when it's run from the web server.

The other solution I came up with (from actually reading the documentation instead of skimming it), is to use this:
import urllib
import sqlalchemy
from sqlalchemy import create_engine
url = urllib.quote_plus('DSN=STAGEDB;UID=username;PWD=password;DATABASE=MY_DB')
engine = create_engine('mssql+pyodbc:///?odbc_connect=' + url)
engine.connect()
Works a treat.
End update

What a combination...

Had a fair bit of trouble with this one. I'm using the iODBC that ships with Mac OSX and FreeTDS as the driver (that's already up and running for PHP to connect to MSSQL).

Here and here suggest methods to get it installed, none of which worked. Turns out the odbc.ini and odbcinst.ini files have no place in /etc/ or /usr/local/etc on Mac OSX, instead they need to be placed in /Library/ODBC. (Can probably set system wide ODBCINI and ODBCSYSINI env vars but it's a bridge too far at this point...)

The odbcinst.ini is:
[FreeTDS]
Description = FreeTDS Driver
Driver = /usr/local/freetds/lib/libtdsodbc.so
and the odbc.ini (which defines the DSNs) is:
[STAGEDB]
Description = stage
Driver = FreeTDS
Servername = STAGEDB

Ok, so that means this script (just using pyodbc) works fine:
import pyodbc
url = 'DSN=STAGEDB;UID=username;PWD=password;PORT=1433;DATABASE=MY_DB;'
conn = pyodbc.connect(url)

But this doesn't:
import sqlalchemy
from sqlalchemy import create_engine
url = 'mssql://usernamer:password@STAGEDB'
engine = create_engine(url)
engine.connect()

Well, it connects to the database server using the DSN called "STAGEDB" but because the database isn't set, then it's not connecting to a specific database, and you can't simply tell it to connect to a database after this connection has been established (I had a read of the API which didn't help and maybe that's not how db connections are even able to operate – beyond my ken).

So the first solution is to try this in the script instead:
url = 'mssql://username:password@STAGEDB/MY_DB'
But this doesn't work – because we are using pyodbc for the connection, it can only connect by using a DSN (and I can't see how to alter this), and in this case the DSN it's looking for is "STAGEDB/MY_DB" and that's not defined.

So it means I have to define a DSN in the odbc.ini file for every combination of database and database server I want to connect to, for example:
[STAGEDB_MYDB]
Description = stage
Driver = FreeTDS
Servername = STAGEDB
Database = MY_DB

Seems like I'm doing something wrong, but I'm not getting it to work any other way.
 1

About

User

Remember me on this computer?