Repository: pyinstaller/pyinstaller

Issue:
Failing to load sqlalchemy-plugin in pyinstaller'ed exe
This line of code works perfectly fine while running as a file from spyder.

engine =  sqlalchemy.create_engine('teradata://uid:pwd@DBinstance?driver=Teradata')
However, after making an exe file using pyinstaller, I get the following error while running the exe:

sqlalchemy.exc.NoSuchModuleError: Can't load plugin:sqlalchemy.dialects:teradata

This looks to be an exe-creation-issue in loading libraries. Has anyone encountered a similar issue and was able to resolve? Any pointers would be appreciated.


Discussion:
similar problem, any help?
To get the Teradata Queries to run on the .exe produced by Pyinstaller. I changed my engine from SQLAlchemy to Teradata  

From :
 

```
    import sqlalchemy as sa
    user, pasw, hostname = UserName,Password, 'myurl.com'
    # connect
    td_engine = sa.create_engine('teradata://{}:{}@{}:22/'.format(user,pasw,hostname),echo=True)
    df = pd.read_sql_query(query1,connect)
```


To:  


```
    import teradata
    user, pasw, hostname = UserName,Password, 'myurl.com'
    td = teradata.UdaExec (appName="test", version="1.0", logConsole=True)
    td_engine = td.connect(method="odbc",system=hostname, username=user,password=pasw,driver="Teradata") 
```


Similar problem I'm getting can anyone help me?
Please refer this issue - https://github.com/ibmdb/python-ibmdbsa/issues/143
The error I'm getting is below

```
`[19460] PyInstaller Bootloader 6.x
[19460] LOADER: executable is C:\Users\bchoudhary\ibmdb12.1\app\dist\sqlalchemySample\sqlalchemySample.exe
[19460] LOADER: _MEIPASS2 is not set
[19460] LOADER: archivename is C:\Users\bchoudhary\ibmdb12.1\app\dist\sqlalchemySample\sqlalchemySample.exe
[19460] LOADER: Cookie found at offset 0x50803F
[19460] LOADER: No need to extract files to run; setting extractionpath to homepath
[19460] LOADER: SetDllDirectory(C:\Users\bchoudhary\ibmdb12.1\app\dist\sqlalchemySample\_internal)
[19460] LOADER: Already in the child - running user's code.
[19460] LOADER: Python library: C:\Users\bchoudhary\ibmdb12.1\app\dist\sqlalchemySample\_internal\python312.dll
[19460] LOADER: Loaded functions from Python library.
[19460] LOADER: Pre-initializing embedded python interpreter...
[19460] LOADER: Creating PyConfig structure...
[19460] LOADER: Initializing interpreter configuration...
[19460] LOADER: Setting program name...
[19460] LOADER: Setting python home path...
[19460] LOADER: Setting module search paths...
[19460] LOADER: Setting sys.argv...
[19460] LOADER: Applying run-time options...
[19460] LOADER: Starting embedded python interpreter...
[19460] LOADER: setting sys._MEIPASS
[19460] LOADER: importing modules from CArchive
[19460] LOADER: extracted struct
[19460] LOADER: running unmarshalled code object for struct...
[19460] LOADER: extracted pyimod01_archive
[19460] LOADER: running unmarshalled code object for pyimod01_archive...
[19460] LOADER: extracted pyimod02_importers
[19460] LOADER: running unmarshalled code object for pyimod02_importers...
[19460] LOADER: extracted pyimod03_ctypes
[19460] LOADER: running unmarshalled code object for pyimod03_ctypes...
[19460] LOADER: extracted pyimod04_pywin32
[19460] LOADER: running unmarshalled code object for pyimod04_pywin32...
[19460] LOADER: Installing PYZ archive with Python modules.
[19460] LOADER: PYZ archive: PYZ-00.pyz
[19460] LOADER: Running pyiboot01_bootstrap.py
[19460] LOADER: Running pyi_rth_inspect.py
[19460] LOADER: Running pyi_rth_pkgutil.py
[19460] LOADER: Running pyi_rth_multiprocessing.py
[19460] LOADER: Running sqlalchemySample.py
Traceback (most recent call last):
  File "sqlalchemySample.py", line 14, in <module>
  File "<string>", line 2, in create_engine
  File "sqlalchemy\util\deprecations.py", line 281, in warned
  File "sqlalchemy\engine\create.py", line 552, in create_engine
  File "sqlalchemy\engine\url.py", line 755, in _get_entrypoint
  File "sqlalchemy\util\langhelpers.py", line 374, in load
sqlalchemy.exc.NoSuchModuleError: Can't load plugin: sqlalchemy.dialects:ibm_db_sa
[19460] Failed to execute script 'sqlalchemySample' due to unhandled exception!
[19460] LOADER: ERROR.
[19460] LOADER: Manually flushing stdout and stderr
[19460] LOADER: Cleaning up Python interpreter.`
```
The sqlalchemy plugins are discovered via entry-points, so you need to collect metadata and add the module to hiddenimports.

In the case of `ibm_db_sa`, add `--copy-metadata ibm-db-sa --hiddenimport ibm_db_sa` to your PyInstaller command.

If you get missing-module errors for modules from `ibm_db_sa`, replace `--hiddenimport ibm_db_sa` with `--collect-submodules ibm_db_sa`.


Resolving patch:
diff --git a/PyInstaller/hooks/hook-sqlalchemy.py b/PyInstaller/hooks/hook-sqlalchemy.py
--- a/PyInstaller/hooks/hook-sqlalchemy.py
+++ b/PyInstaller/hooks/hook-sqlalchemy.py
@@ -14,7 +14,9 @@
 
 from PyInstaller import isolated
 from PyInstaller.lib.modulegraph.modulegraph import SourceModule
-from PyInstaller.utils.hooks import check_requirement, logger
+from PyInstaller.utils.hooks import check_requirement, collect_entry_point, logger
+
+datas = []
 
 # 'sqlalchemy.testing' causes bundling a lot of unnecessary modules.
 excludedimports = ['sqlalchemy.testing']
@@ -41,6 +43,13 @@ def _get_dialect_modules(module_name):
 else:
     hiddenimports += _get_dialect_modules("sqlalchemy.databases")
 
+# Collect additional dialects and plugins that are registered via entry-points, under assumption that they are available
+# in the build environment for a reason (i.e., they are used).
+for entry_point_name in ('sqlalchemy.dialects', 'sqlalchemy.plugins'):
+    ep_datas, ep_hiddenimports = collect_entry_point(entry_point_name)
+    datas += ep_datas
+    hiddenimports += ep_hiddenimports
+
 
 def hook(hook_api):
     """


Test patch: