Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to bundle cx_oracle with Pyinstaller

My goal is to use Pyinstaller to bundle an exe file from a simple python script that uses Tkinter and cx_oracle to access a database. The python code is developed on a windows machine with Anaconda, cx_oracle package and oracle client installed. Then I need to run the exe file in many target windows machines without oracle client or Python.

I am using Python 2.7 and Pyinstaller 3.1 on the development machine.

I searched quite a while online but only found one tutorial on this: https://mail.python.org/pipermail/tutor/2014-December/103608.html

I followed the same procedure and modified the spec file as below:

# -*- mode: python -*-

block_cipher = None


a = Analysis(['mycode.py'],
             pathex=['C:\\Users\\myuser\\PycharmProjects\\mycode'],
             binaries=None,
             datas=None,
             hiddenimports=[],
             hookspath=[],
             runtime_hooks=[],
             excludes=[],
             win_no_prefer_redirects=False,
             win_private_assemblies=False,
             cipher=block_cipher)
pyz = PYZ(a.pure, a.zipped_data,
             cipher=block_cipher)
exe = EXE(pyz,
          a.scripts,
          a.binaries + [('oraociei11.dll','D:\ProgramFiles\Anaconda2\oraociei11.dll','BINARY')],
          a.zipfiles,
          a.datas,
          name='mycode',
          debug=False,
          strip=False,
          upx=True,
          console=True )

the bundle worked. The code runs on the original machine with oracle client installed. But on a separate machine without oracle client, it failed to run, with the below error message:

Exception in Tkinter callback Traceback (most recent call last): File "lib-tk\Tkinter.py", line 1537, in call File "", line 152, in login DatabaseError: DPI-1047: 64-bit Oracle Client library cannot be loaded: "The specified module could not be found". See https://oracle.github.io/odpi/doc/installation.html#windows for help

Now I am very confused what are the required steps to safely bundle an exe from a python script with cx_oracle so that it can run on a windows machine without oracle client? Or do I "have to" install oracle client on the target machine?

I really hope to find a more detailed tutorial on bundling cx_oracle with pyinstaller than the old link I found above.

like image 966
Pan Yan Avatar asked Dec 02 '17 02:12

Pan Yan


People also ask

How to bundle a python application using pyinstaller?

To bundle a python application, the basic usage is: To use pyinstaller correctly, we should remmember some basic pyinstaller parameters. Here we will introduce some pyinstaller parameters we often use. As to example above, we will generate a PNG2EPS.exe in dist folder.

How to use CX_Oracle 8 with Python and Oracle Database?

To use cx_Oracle 8 with Python and Oracle Database you need: Python 3.5 and higher. Older versions of cx_Oracle may work with older versions of Python. Oracle Client libraries.

How do I install Oracle client libraries on PyPI?

You must set LD_LIBRARY_PATH or use ldconfig to locate the Oracle client library. PyPI no longer allows Windows installers or Linux RPMs to be hosted. Use the supplied cx_Oracle Wheels instead, or use RPMs from Oracle, see Installing cx_Oracle RPMs on Oracle Linux.

Which Oracle client libraries are supported with Python?

These can be from the free Oracle Instant Client, from a full Oracle Client installation, or from those included in Oracle Database if Python is on the same machine as the database. Oracle client libraries versions 21, 19, 18, 12, and 11.2 are supported where available on Linux, Windows and macOS (Intel x86).


2 Answers

cx_Oracle requires an Oracle client. You will need to install that on the target machine! Note the link in the error message: https://oracle.github.io/odpi/doc/installation.html#windows. It should help you out with everything you need to do to get cx_Oracle working on the target machine.

like image 175
Anthony Tuininga Avatar answered Oct 09 '22 22:10

Anthony Tuininga


Thank you for posting this question. You are on the right path. You are only missing other .dll files. You need to add all .dll files found in your Oracle instant client folder to the .spec file. See below for an example I did for instant client 19.10:

a.binaries = a.binaries + [('oraociei19.dll','.\\instantclient_19_10\\oraociei19.dll','BINARY')]
+ [('orannzsbb19.dll','.\\instantclient_19_10\\orannzsbb19.dll','BINARY')]
+ [('oraocci19d.dll','.\\instantclient_19_10\\oraocci19d.dll','BINARY')]
+ [('oraocci19.dll','.\\instantclient_19_10\\oraocci19.dll','BINARY')]
+ [('oci.dll','.\\instantclient_19_10\\oci.dll','BINARY')]
+ [('ocijdbc19.dll','.\\instantclient_19_10\\ocijdbc19.dll','BINARY')]
+ [('ociw32.dll','.\\instantclient_19_10\\ociw32.dll','BINARY')]
+ [('oramysql19.dll','.\\instantclient_19_10\\oramysql19.dll','BINARY')]
+ [('oraons.dll','.\\instantclient_19_10\\oraons.dll','BINARY')]
+ [('orasql19.dll','.\\instantclient_19_10\\orasql19.dll','BINARY')]
like image 20
Al Nazari Avatar answered Oct 09 '22 22:10

Al Nazari