zillow / ctds

Python DB-API 2.0 library for MS SQL Server
MIT License
83 stars 12 forks source link

Can't Import _tds when calling import ctds #81

Open hub-il opened 3 years ago

hub-il commented 3 years ago

I'm using Windows 10 and I have successfully built the tds library using the provided freetds-install.ps1 script and I have been able to install ctds from pip. However when I import ctds I get the error:

  File "C:\Users\xxxxxx\AppData\Local\Programs\Python\Python38\lib\site-packages\ctds\__init__.py", line 8, in <module>
    from _tds import (

I have added the \libs folder to my Path and have also copied the files from the \libs folder into the working directory reported by os.getcwd()

This is the same issue that was described in https://github.com/zillow/ctds/issues/24 but I was not able to resolve the issue by including the \libs in the path.

joshuahlang commented 3 years ago

(going off memory here since I haven't developed on Windows in a while) I suspect the windows library loader can't locate some DLL. Can you try running a tool like https://github.com/lucasg/Dependencies on the _tds.*.pyd file and see if the tool reports that all DLLs are found?

hub-il commented 3 years ago

Sorry for the delay in getting back to you. The sybdb.dll and ct.dll dlls were NOT found as you suspected when I used the "Dependencies" program on _tds..pyd. I was able to get the dll's loaded by ctds when I copied those dll files into the same directory as the _tds..pyd file. I have not been able to get them to work by appending the path to the DLL's to the PATH environmental variable. I have tried updating the path in a normal CMD command prompt and in PowerShell prompt without success event those when I echo the %PATH% variable the path to the dlls does appear in the variable.

Would it be possible to specify a separate environmental variable just for the those required dlls and have the _tds.*.pyd file try to load the dll's from that location as an alternative? Ideally, what I would like do is see if I can include the dll files in the git repository for my program so that when other members of my team clone the repository and run it they don't have to copy those files to a custom location on their machines.

joshuahlang commented 3 years ago

I don't think this is possible to do programmatically in the ctds code itself as the failure occurs when the Windows library loader is trying to load the ctds code and fails due to the missing linked OpenSSL libraries. In other words the error occurs before any ctds code could execute. There may be some way to address this with a manifest or some other Windows-specific mechanism that I'm not familiar with. I haven't developed on Windows in many years, so I'm open to suggestions from someone with more knowledge of Windows development.

hub-il commented 3 years ago

So here was my work around to make this work. I was able to use sudo code to dynamically load the dll files from a location specified by me. Seems to be working well.

sybdb_path = ".\\app\\tds\\lib\\sybdb.dll"
ct_path = ".\\app\\tds\\lib\\ct.dll"

if current_platform == 'windows':
    import ctypes
    sybdb = ctypes.WinDLL(sybdb_path)
    ct = ctypes.WinDLL(ct_path)
    import ctds