pyodbc icon indicating copy to clipboard operation
pyodbc copied to clipboard

Changing location of libodbc.2.dylib on macOS

Open paw-lu opened this issue 5 years ago • 18 comments

Environment

To diagnose, we usually need to know the following, including version numbers. On Windows, be sure to specify 32-bit Python or 64-bit:

  • Python: 3.7.6
  • pyodbc: 4.0.28
  • OS: macOS 10.14.4
  • driver: freetds

Issue

When importing pyodbc

❯ python
>>> import pyodbc
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ImportError: dlopen(/Users/pcosta/Documents/test/myenv/lib/python3.7/site-packages/pyodbc.cpython-37m-darwin.so, 2): Library not loaded: /usr/local/opt/unixodbc/lib/libodbc.2.dylib
  Referenced from: /Users/pcosta/Documents/test/myenv/lib/python3.7/site-packages/pyodbc.cpython-37m-darwin.so
  Reason: image not found

I know why this is happening, as I don't have libodbc.2.dylib in the expected location. The reason is I do not have permission to write to /usr/local/, so I have Homebrew installing into ~/.brew. This mostly works fine. I am even able to get both tsql and isql working as expected by following the steps outlined here: https://github.com/mkleehammer/pyodbc/wiki/Connecting-to-SQL-Server-from-Mac-OSX.

So I do have libodbc.2.dylib, it's just that it lives in /Users/pcosta/.brew/opt/unixodbc/lib, not /usr/local/opt/unixodbc/lib.

The main questions is can I get pyodbc to look for libodbc.2.dylib (and other associated files) in another directory?

I have all the files needed and have configured them correctly, I just need to repoint pyodbc somehow.

Thanks!

paw-lu avatar Jan 13 '20 23:01 paw-lu

I would recommend using the latest unixODBC rather then iodbc, there is more discussion here: https://github.com/mkleehammer/pyodbc/issues/444

v-makouz avatar Jan 14 '20 19:01 v-makouz

To the best of my knowledge, I am using unixODBC.

paw-lu avatar Jan 14 '20 19:01 paw-lu

FWIW, the path appears to be hard-coded into the .so file:

hex dump

gordthompson avatar Jan 14 '20 23:01 gordthompson

Ah good find! Not sure if I can work around it then.

paw-lu avatar Jan 15 '20 00:01 paw-lu

If the pre-compiled wheel file won't work for you then you could try installing from source ...

pip install --no-binary pyodbc pyodbc

... but you'd need to have a C++ compiler and the unixODBC development (header) files on your machine for that to work.

gordthompson avatar Jan 15 '20 12:01 gordthompson

I looked into it a bit more and it looks like if you ldd that .so file you can see /usr/local/lib/libodbc.2.dylib, I tried using install_name_tool to change the dependency, but after that I started getting "ImportError: No module named pyodbc".

When I have time I want to investigate it further, but the .so file seems to be created if you run python setup.py install if you want to build it yourself from source

v-makouz avatar Jan 15 '20 16:01 v-makouz

Want to thank both @gordthompson and @v-makouz for their response, it's been super appreciated.

I didn't bring it up initially, but I have tried to build from source and that also seems to run into issues.

~
❯ pip install --no-binary pyodbc pyodbc
...
    In file included from src/buffer.cpp:12:
    src/pyodbc.h:56:10: fatal error: 'sql.h' file not found
    #include <sql.h>
             ^~~~~~~
    1 error generated.
    error: command 'clang' failed with exit status 1
    ----------------------------------------
...

Which mirrors some of the issues shown in #101

Like before, I know sql.h exists...

~
❯ cd ~/homebrew

~/homebrew stable
❯ find . -name 'sql.h'
./include/sql.h
./Cellar/unixodbc/2.3.7/include/sql.h

So again when PyODBC looks for sql.h on this line it misses the homebrew file.

P.S. I changed the directory from ~/brew to ~/homebrew because I saw these lines in setup.py. So I thought if I renamed ~/.brew/include to ~/homebrew/include it would be able to locate sql.h. It did not work.

paw-lu avatar Jan 15 '20 20:01 paw-lu

Want to update the issue with my solution.

The clang issues can be solved by adding unixODBC's path to these environmental variables:

export LDFLAGS="-L/Users/pcosta/homebrew/opt/unixodbc/lib $LDFLAGS"
export CPPFLAGS="-I/Users/pcosta/homebrew/opt/unixodbc/include $CPPFLAGS"
export PKG_CONFIG_PATH="/Users/pcosta/homebrew/opt/unixodbc/lib/pkgconfig $PKG_CONFIG_PATH"

This makes it possible to run pip install --no-binary pyodbc pyodbc with an atypical installation directory.

It would be nice if users would be able to specify locations of drivers to avoid the build process, but I realize this is a specific edge case.

paw-lu avatar Jan 16 '20 17:01 paw-lu

I don't think this is a specific edge case. It holds for all mac users who use homebrew or macports (like me). So I would vote for reopening this issue.

Thomasillo avatar Mar 23 '20 13:03 Thomasillo

@Thomasillo Note that this seems to only apply to the case where you have an atypical homebrew installation.

In my case, I had installed homebrew into ~/homebrew. I believe (have not tested) that the installation should work without issue if you install homebrew as recommended (/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install.sh).

If you think this is not the case, I'd be happy to reopen if you're having issues.

paw-lu avatar Mar 23 '20 18:03 paw-lu

It applies also to the typical mac ports install directory. /opt/local I was having this issue but fixed it with your directions. :) I just thought after stumbling over quite some other posts with this, that it should be treated in a more general way.

Thomasillo avatar Mar 23 '20 19:03 Thomasillo

Gotcha @Thomasillo.

Glad my instructions helped you out!

I have never used MacPorts—so thanks for the clarification. That sounds fair. I'll reopen the issue.

The official ask then is to allow for more flexibility for the location of the necessary unixODBC files when installing pyodbc as a wheel.

paw-lu avatar Mar 23 '20 21:03 paw-lu

Yes, I spent an afternoon spinning my wheels on this one. If you install your unixODBC and FreeTDS via MacPorts, you are just. out of luck--pyodbc will not see them. It would be nice to have an package installer-agnostic way of making all this work.

fonnesbeck avatar Dec 02 '20 15:12 fonnesbeck

Due to how the Mac dynamic linking system works, there will be hardcoded absolute paths in the binaries. It's not really possible to work around that without adding own dynamic searching and loading logic, which can be quite complex.

v-chojas avatar Dec 02 '20 20:12 v-chojas

@v-chojas Previous versions of pylib for Darwin were looking for libodbc.2.dylib at Python lib folder Now it is looking for it in /usr/local/lib Is it possible to search in both locations? Or it is also too complex? If so, maybe searching in Python lib folder (old behaviour) is better, since symlinks can be used for flexibility.

AntonM030481 avatar Sep 21 '21 13:09 AntonM030481

Facing same issue, the file libodbc.2.dylib is not available after unixodbc installation, Why M3 Silicon chip is behaving weird? Anybody solved this issue?

Himanshup21234 avatar Apr 16 '24 10:04 Himanshup21234