首页 > 解决方案 > OSError: dlopen(libiodbc.dylib, 6): image not found (Mac Big Sur, Python3.8)

问题描述

我刚刚将我的 Mac 从 Mojave 升级到 Big Sur,并重新安装了 Anaconda 和 teradata ODBC。在我的 Python(3.8) 代码中,我使用 sqlalchemy-teradata 连接到 teradata。这曾经可以工作,但在所有升级之后,我的代码在从 teradata 提取数据时会引发以下错误:

--> 166         demand=pd.read_sql(sql, con=cnxn)
    167     except:
    168         print("sql string: "+sql)

~/opt/anaconda3/lib/python3.8/site-packages/pandas/io/sql.py in read_sql(sql, con, index_col, coerce_float, params, parse_dates, columns, chunksize)
    507         )
    508     else:
--> 509         return pandas_sql.read_query(
    510             sql,
    511             index_col=index_col,

~/opt/anaconda3/lib/python3.8/site-packages/pandas/io/sql.py in read_query(self, sql, index_col, coerce_float, parse_dates, params, chunksize)
   1293         args = _convert_params(sql, params)
   1294 
-> 1295         result = self.execute(*args)
   1296         columns = result.keys()
   1297 

~/opt/anaconda3/lib/python3.8/site-packages/pandas/io/sql.py in execute(self, *args, **kwargs)
   1159     def execute(self, *args, **kwargs):
   1160         """Simple passthrough to SQLAlchemy connectable"""
-> 1161         return self.connectable.execution_options(no_parameters=True).execute(
   1162             *args, **kwargs
   1163         )

~/opt/anaconda3/lib/python3.8/site-packages/sqlalchemy/engine/base.py in execute(self, statement, *multiparams, **params)
   2232         """
   2233 
-> 2234         connection = self._contextual_connect(close_with_result=True)
   2235         return connection.execute(statement, *multiparams, **params)
   2236 

~/opt/anaconda3/lib/python3.8/site-packages/sqlalchemy/engine/base.py in _contextual_connect(self, close_with_result, **kwargs)
   2300         return self._connection_cls(
   2301             self,
-> 2302             self._wrap_pool_connect(self.pool.connect, None),
   2303             close_with_result=close_with_result,
   2304             **kwargs

~/opt/anaconda3/lib/python3.8/site-packages/sqlalchemy/engine/base.py in _wrap_pool_connect(self, fn, connection)
   2334         dialect = self.dialect
   2335         try:
-> 2336             return fn()
   2337         except dialect.dbapi.Error as e:
   2338             if connection is None:

~/opt/anaconda3/lib/python3.8/site-packages/sqlalchemy/pool/impl.py in connect(self)
    364                 return rec._checkout_existing()
    365 
--> 366         return _ConnectionFairy._checkout(self, self._fairy)
    367 
    368     def _return_conn(self, record):

~/opt/anaconda3/lib/python3.8/site-packages/sqlalchemy/pool/base.py in _checkout(cls, pool, threadconns, fairy)
    776     def _checkout(cls, pool, threadconns=None, fairy=None):
    777         if not fairy:
--> 778             fairy = _ConnectionRecord.checkout(pool)
    779 
    780             fairy._pool = pool

~/opt/anaconda3/lib/python3.8/site-packages/sqlalchemy/pool/base.py in checkout(cls, pool)
    493     @classmethod
    494     def checkout(cls, pool):
--> 495         rec = pool._do_get()
    496         try:
    497             dbapi_connection = rec.get_connection()

~/opt/anaconda3/lib/python3.8/site-packages/sqlalchemy/pool/impl.py in _do_get(self)
    347         except AttributeError:
    348             pass
--> 349         c = self._create_connection()
    350         self._conn.current = weakref.ref(c)
    351         if len(self._all_conns) >= self.size:

~/opt/anaconda3/lib/python3.8/site-packages/sqlalchemy/pool/base.py in _create_connection(self)
    307         """Called by subclasses to create a new ConnectionRecord."""
    308 
--> 309         return _ConnectionRecord(self)
    310 
    311     def _invalidate(self, connection, exception=None, _checkin=True):

~/opt/anaconda3/lib/python3.8/site-packages/sqlalchemy/pool/base.py in __init__(self, pool, connect)
    438         self.__pool = pool
    439         if connect:
--> 440             self.__connect(first_connect_check=True)
    441         self.finalize_callback = deque()
    442 

~/opt/anaconda3/lib/python3.8/site-packages/sqlalchemy/pool/base.py in __connect(self, first_connect_check)
    659         except Exception as e:
    660             with util.safe_reraise():
--> 661                 pool.logger.debug("Error on connect(): %s", e)
    662         else:
    663             if first_connect_check:

~/opt/anaconda3/lib/python3.8/site-packages/sqlalchemy/util/langhelpers.py in __exit__(self, type_, value, traceback)
     66             self._exc_info = None  # remove potential circular references
     67             if not self.warn_only:
---> 68                 compat.raise_(
     69                     exc_value,
     70                     with_traceback=exc_tb,

~/opt/anaconda3/lib/python3.8/site-packages/sqlalchemy/util/compat.py in raise_(***failed resolving arguments***)
    180 
    181         try:
--> 182             raise exception
    183         finally:
    184             # credit to

~/opt/anaconda3/lib/python3.8/site-packages/sqlalchemy/pool/base.py in __connect(self, first_connect_check)
    654         try:
    655             self.starttime = time.time()
--> 656             connection = pool._invoke_creator(self)
    657             pool.logger.debug("Created new connection %r", connection)
    658             self.connection = connection

~/opt/anaconda3/lib/python3.8/site-packages/sqlalchemy/engine/strategies.py in connect(connection_record)
    112                         if connection is not None:
    113                             return connection
--> 114                 return dialect.connect(*cargs, **cparams)
    115 
    116             creator = pop_kwarg("creator", connect)

~/opt/anaconda3/lib/python3.8/site-packages/sqlalchemy/engine/default.py in connect(self, *cargs, **cparams)
    491     def connect(self, *cargs, **cparams):
    492         # inherits the docstring from interfaces.Dialect.connect
--> 493         return self.dbapi.connect(*cargs, **cparams)
    494 
    495     def create_connect_args(self, url):

~/opt/anaconda3/lib/python3.8/site-packages/teradata/tdodbc.py in __init__(self, dbType, system, username, password, autoCommit, transactionMode, queryBands, odbcLibPath, dataTypeConverter, driver, **kwargs)
    419 
    420         # Initialize connection handle
--> 421         init(odbcLibPath)
    422 
    423         # Build connect string

~/opt/anaconda3/lib/python3.8/site-packages/teradata/tdodbc.py in init(odbcLibPath)
    364     try:
    365         lock.acquire()
--> 366         initOdbcLibrary(odbcLibPath)
    367         initFunctionPrototypes()
    368         initOdbcEnv()

~/opt/anaconda3/lib/python3.8/site-packages/teradata/tdodbc.py in initOdbcLibrary(odbcLibPath)
    317                     odbcLibPath = 'libodbc.so'
    318             logger.info("Loading ODBC Library: %s", odbcLibPath)
--> 319             odbc = ctypes.cdll.LoadLibrary(odbcLibPath)
    320 
    321 

~/opt/anaconda3/lib/python3.8/ctypes/__init__.py in LoadLibrary(self, name)
    457 
    458     def LoadLibrary(self, name):
--> 459         return self._dlltype(name)
    460 
    461 cdll = LibraryLoader(CDLL)

~/opt/anaconda3/lib/python3.8/ctypes/__init__.py in __init__(self, name, mode, handle, use_errno, use_last_error, winmode)
    379 
    380         if handle is None:
--> 381             self._handle = _dlopen(self._name, mode)
    382         else:
    383             self._handle = handle

OSError: dlopen(libiodbc.dylib, 6): image not found

我可以在 /usr/lib 下看到这个 libiodbc.dylib。同样,我的 ODBC 管理器找不到 libiodbcinst.dylib。似乎是同样的问题。我花了 2 天时间寻找解决方案。我尝试禁用 SIP,更新 brew,将 /usr/lib 添加到 DYLD_LIBRARY_PATH,但它们都不起作用。

有人对此有解决方案吗?

标签: pythonsqlalchemyodbcteradatamacos-big-sur

解决方案


推荐阅读