PyTd
PyTd copied to clipboard
ODBC Library(libodbc.so) loading issue in AIX 7.1
Env: OS AIX 7.1.0.0 tdodbc version: 14.10.0.7 xxxxxxxxxx:/opt/teradata/client/ODBC_64/lib: lslpp -l | grep odbc tdodbc1410.tdodbc1410 14.10.0.7 COMMITTED Teradata ODBC Driver for AIX
Tried to use PyTD to connect Teradata in AIX 7.1 but got following error:
Traceback (most recent call last):
File "/opt/freeware/lib64/python3.5/runpy.py", line 184, in _run_module_as_main
"main", mod_spec)
File "/opt/freeware/lib64/python3.5/runpy.py", line 85, in _run_code
exec(code, run_globals)
File "/home/xxxxxx/python/proj/cba/aipl/proj_teradata.py", line 71, in
Python 3.5.2 (default, Dec 1 2016, 02:07:23)
[GCC 4.8.5] on aix6
Type "help", "copyright", "credits" or "license" for more information.
>>> from ctypes import cdll
>>> print(cdll.LoadLibrary("libodbc.so"))
Loading Library: libodbc.so
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/opt/freeware/lib64/python3.5/ctypes/__init__.py", line 437, in LoadLibrary
return self._dlltype(name)
File "/opt/freeware/lib64/python3.5/ctypes/__init__.py", line 357, in __init__
self._handle = _dlopen(self._name, mode)
OSError: 0509-022 Cannot load module .
0509-026 System error: A file or directory in the path name does not exist.
>>>
It turned out there is no file named libodbc.so, but there is one file named "odbc.so" exist in /opt/teradata/client/ODBC_64/lib
xxxxxxxxxx:/opt/teradata/client/ODBC_64/lib: ls -lrt
total 71192
-r--r--r-- 1 bin bin 67068 21 Mar 2015 vscnctdlg.so
-r--r--r-- 1 bin bin 229441 21 Mar 2015 tdconndlg.so
-r--r--r-- 1 bin bin 6020823 21 Mar 2015 tdata.so
-r--r--r-- 1 bin bin 2171709 21 Mar 2015 odbc.so
-r--r--r-- 1 bin bin 1830772 21 Mar 2015 odbcinst.so
-r--r--r-- 1 bin bin 2032897 21 Mar 2015 odbccurs.so
-r--r--r-- 1 grandhsa 30000 1769226 21 Mar 2015 libtdsso.so
-r--r--r-- 1 bin bin 610880 21 Mar 2015 libtdparse.so
-r--r--r-- 1 bin bin 610880 21 Mar 2015 libtdparse.a
-r--r--r-- 1 bin bin 1831194 21 Mar 2015 libodbcinst.a
-r--r--r-- 1 bin bin 2172128 21 Mar 2015 libodbc.a
-r--r--r-- 1 bin bin 15005158 21 Mar 2015 libddicu26.a
-r--r--r-- 1 bin bin 2064704 21 Mar 2015 ddtrc26.so
lrwxrwxrwx 1 root system 31 01 Aug 21:03 libicudatatd.so -> /usr/lib/lib_64/libicudatatd.so
lrwxrwxrwx 1 root system 33 01 Aug 21:03 libicudatatd46.so -> /usr/lib/lib_64/libicudatatd46.so
lrwxrwxrwx 1 root system 31 01 Aug 21:03 libicuiotd46.so -> /usr/lib/lib_64/libicuiotd46.so
lrwxrwxrwx 1 root system 31 01 Aug 21:03 libicui18ntd.so -> /usr/lib/lib_64/libicui18ntd.so
lrwxrwxrwx 1 root system 33 01 Aug 21:03 libicui18ntd46.so -> /usr/lib/lib_64/libicui18ntd46.so
lrwxrwxrwx 1 root system 31 01 Aug 21:03 libiculetd46.so -> /usr/lib/lib_64/libiculetd46.so
lrwxrwxrwx 1 root system 29 01 Aug 21:03 libicuiotd.so -> /usr/lib/lib_64/libicuiotd.so
lrwxrwxrwx 1 root system 29 01 Aug 21:03 libiculetd.so -> /usr/lib/lib_64/libiculetd.so
lrwxrwxrwx 1 root system 31 01 Aug 21:03 libicuuctd46.so -> /usr/lib/lib_64/libicuuctd46.so
lrwxrwxrwx 1 root system 29 01 Aug 21:03 libiculxtd.so -> /usr/lib/lib_64/libiculxtd.so
lrwxrwxrwx 1 root system 31 01 Aug 21:03 libiculxtd46.so -> /usr/lib/lib_64/libiculxtd46.so
lrwxrwxrwx 1 root system 29 01 Aug 21:03 libicuuctd.so -> /usr/lib/lib_64/libicuuctd.so
lrwxrwxrwx 1 root system 49 01 Aug 21:03 odbctrac.so -> /opt/teradata/client/14.10/odbc_64/lib/ddtrc26.so
lrwxrwxrwx 1 root system 29 01 Aug 21:03 tdwalletdir -> /opt/teradata/client/tdwallet
So, I manually changed the code of function: initOdbcLibrary in tdodbc.py and added hack for AIX, now it is working fine.
def initOdbcLibrary(odbcLibPath=None):
"""Initialize the ODBC Library."""
global odbc
if odbc is None:
if osType == "Windows":
odbc = ctypes.windll.odbc32
else:
if not odbcLibPath:
# If MAC OSx
if osType == "Darwin":
odbcLibPath = "libiodbc.dylib"
elif osType.startswith("CYGWIN"):
odbcLibPath = "odbc32.dll"
# 2018-01-12 Bug fix for AIX teradata TTU 14.10
if osType == "AIX":
odbcLibPath = "odbc.so"
else:
odbcLibPath = 'libodbc.so'
logger.info("Loading ODBC Library: %s", odbcLibPath)
odbc = ctypes.cdll.LoadLibrary(odbcLibPath)
workaround codes:
# 2018-01-12 Bug fix for AIX teradata TTU 14.10
if osType == "AIX":
odbcLibPath = "odbc.so"
Should this workaround to be added in? Do we have testing in AIX flatform?
Thanks, Frank
Hi Frank,
I have not tested PyTd on AIX. You can set odbcLibPath without a code change by passing it as an argument to UdaExec or by specifying it in an external config file. I think we would only add the default value for AIX if it was officially tested on that platform. I will keep this issue open to track interest in officially certifying on AIX.
Thanks, -Eric
Hi Eric,
Did not know that we can specify "odbcLibPath" in external config file. I think I will go with this solution for now.
Thanks for your help.
Regards, Frank
Hi Frank and Eric,
Glad to find this discussion, as I've also struggled to connect to Python to Teradata from AIX 7.1. Defining the odbcLibPath was critical, but I found it only works when placed in the udaexec.ini and NOT when passed as a UdaExec parameter.
I also found (in another post) that I had to define Authentication=LDAP. Strangely, this only works as a UdaExec parameter but NOT in the udaexec.ini (converse to the odbcLibPath)! Beyond the finicky location, this confuses me for other reasons... first, because the Teradata Python Module documentation doesn't include Authentication among UdaExec's valid parms, but also because I had already declared "Authentication=LDAP" in the odbc.ini config, within my DSN section. Why doesn't it work there?
Here is my sample Python program (which works):
import teradata udaExec = teradata.UdaExec(appName="Test1", version="1.0") with udaExec.connect(method="odbc", authentication="LDAP", system="tdt", username="xxx", password="$$tdwallet(xxx)") as myses: ...
My udaexec.ini file: `[CONFIG] logConsole=True
[DEFAULT] odbcLibPath=/opt/teradata/client/ODBC_64/lib/odbc.so `
And finally, my /opt/teradata/client/ODBC_64/odbc.ini file: `[ODBC] InstallDir=/opt/teradata/client/ODBC_64 Trace=0 TraceDll=/opt/teradata/client/ODBC_64/lib/odbctrac.so TraceFile=/usr/joe/odbcusr/trace.log TraceAutoStop=0
[ODBC Data Sources] tdt=tdata.so
[tdt] Driver=/opt/teradata/client/ODBC_64/lib/tdata.so Description=Teradata Test database DBCName=tdt Authentication=LDAP Charset=UTF-8`
Optimally, I want to place as much config as possible in external files to keep our programs cleaner, so I'd like to move the "method" and "authentication" to external configs, but attempting to do so breaks the db connection. Any insight you can offer is appreciated.
Thanks, Dan
Hi @djb18
I never use ODBC DSN as 'system', I always put all parameters into a external config file. you need ensure ODBC driver info in file: /opt/teradata/client/ODBC_64/odbcinst.ini is correct.
Frank
Hi Guys,
I am stuck on the same issue here - I tried to pass an alternative value of odbcLibPath, but in both cases (in config, and passing as a param), I get the same error:
using: odbcLibPath=/opt/teradata/client/ODBC_64/lib/odbc.
File "/opt/freeware/lib64/python3.5/teradata/udaexec.py", line 183, in connect **args)) TypeError: type object got multiple values for keyword argument 'odbcLibPath'
Any assistance gratefully received. Soberoo