在docker中为python项目加载Teradata ODBC驱动程序时出错

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了在docker中为python项目加载Teradata ODBC驱动程序时出错相关的知识,希望对你有一定的参考价值。

我正在尝试使用python teradata模块连接到Teradata数据库。但是当我在docker中运行我的应用程序时,我会遇到异常::

File "/usr/local/lib/python3.7/site-packages/teradata/udaexec.py", line 183, in connect
    **args))
  File "/usr/local/lib/python3.7/site-packages/teradata/tdodbc.py", line 421, in __init__
    init(odbcLibPath)
  File "/usr/local/lib/python3.7/site-packages/teradata/tdodbc.py", line 366, in init
    initOdbcLibrary(odbcLibPath)
  File "/usr/local/lib/python3.7/site-packages/teradata/tdodbc.py", line 319, in initOdbcLibrary
    odbc = ctypes.cdll.LoadLibrary(odbcLibPath)
  File "/usr/local/lib/python3.7/ctypes/__init__.py", line 434, in LoadLibrary
    return self._dlltype(name)
  File "/usr/local/lib/python3.7/ctypes/__init__.py", line 356, in __init__
    self._handle = _dlopen(self._name, mode)
OSError: Error relocating /opt/teradata/client/16.20/lib64/libodbc.so: _toupper: symbol not found

我在我的Windows机器上运行相同的代码,但问题是我在Docker中运行相同的代码。在我的Windows机器上安装了Teradata ODBC 16.20,但是当我尝试在docker中做同样的事情时,我可能会错过一些东西,因为我是docker的新手。

Docker文件::

FROM python:alpine3.7

ADD test.py /
USER root
ADD tdodbc1620__linux_indep.16.20.00.54-1.tar.gz /tmp/
RUN apk add rpm
RUN rpm -ivh /tmp/tdodbc1620/tdodbc1620-16.20.00.54-1.noarch.rpm --prefix=/opt/ --nodeps    
RUN cp /opt/teradata/client/ODBC_64/odbc.ini ~/.odbc.ini
RUN cp /opt/teradata/client/ODBC_64/odbcinst.ini ~/.odbcinst.ini    
RUN pip install --upgrade pip
RUN pip install teradata        
ENV ODBCHOME=/opt/teradata/client/ODBC_64/ ODBCINI=/opt/teradata/client/ODBC_64/odbc.ini ODBCINST=/opt/teradata/client/ODBC_64/odbcinst.ini
ENV LD_LIBRARY_PATH $LD_LIBRARY_PATH:/opt/teradata/client/16.20/lib64    
RUN chown -R root /opt/teradata/client/16.20/lib64/*.so    
CMD [ "python", "./test.py" ]

Python代码::

import teradata

udaExec = teradata.UdaExec (appName="HelloWorld", version="1.0", logConsole=False)
session = udaExec.connect(method='odbc', system='xyz.com', username='xyz', password='xyz', AUTHENTICATION='LDAP')

with session as connect :
    for row in connect.execute("`select top 5 * from EMPLOYEE;`"):
        print(row)

预期结果::打印EMPLOYEE表中的前5行。

使用RHEL OS的Docker文件的最新副本:

FROM quay.********/rhel:latest

ADD test.py /
USER root
RUN yum --nogpgcheck -y install unzip sudo vim wget which tar gzip graphviz python-setuptools python-setuptools-devel shadow-utils git net-tools libXtst.x86_64 python-pip 
RUN yum -y install libgcc_s.so.1
RUN yum -y install libstdc++.so.6

ADD tdodbc1620__linux_indep.16.20.00.54-1.tar.gz ./

RUN cd /tdodbc1620/ &&  
    ./setup_wrapper.sh -s -r tdodbc1620-16.20.00.54-1.noarch.rpm

RUN  pip install teradata

ENV ODBCHOME=/opt/teradata/client/ODBC_64 
ENV ODBCINI=$ODBCHOME/odbc.ini 
ENV ODBCINST=$ODBCHOME/odbcinst.ini
ENV LD_LIBRARY_PATH=$ODBCHOME/lib:$LD_LIBRARY_PATH
答案

该错误表明操作系统在加载ODBC驱动程序的二进制库时无法解析符号_toupper。标准C函数如touppersnprintf等由C运行时库提供。

为了最小化图像大小,Alpine Linux建立在标准C运行时的musl实现上。大多数其他Linux发行版都使用GNU C库(glibc)。 Musl旨在实现符合ISO C和POSIX标准的轻量级快速实现,因此大多数应用程序不需要或只需要很少的源代码更改就可以编译。但是ABI(应用程序二进制接口)兼容性非常有限,因此使用glibc编译的许多二进制文件将无法与musl一起运行。

如果从源代码重新编译ODBC驱动程序不是一个选项,最简单的方法是从Alpine切换到具有glibc运行时的基本映像,与ODBC驱动程序二进制文件所需的相同。

以上是关于在docker中为python项目加载Teradata ODBC驱动程序时出错的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Linux 中为 Rider 设置 Docker

如何在 Python 中为不和谐的机器人创建重新加载命令?

在基于 docker 的 GitLab CI 设置中为 maven 存储 settings.xml 的位置

docker-compose 时出错“/usr/local/bin/python:加载共享库时出错:libpython3.8.so.1.0:”

在 pipenv 项目中为 python 文件创建命令行别名

在 Python 中为 Dataflow 管道使用 WriteToBigquery 时出错。 Unicode 对象没有属性“项目”