25. Extending python-oracledb — python-oracledb 3.2.0b1 documentation (original) (raw)
You can extend the capabilities of python-oracledb by using standard Python functionality for subclassing python-oracledb classes. You can also use python-oracledb plugins,connection protocol hooks, connection password hooks, and connection parameter hooks.
25.1. Subclassing Connections
Subclassing enables applications to change python-oracledb, for example by extending connection and statement execution behavior. This can be used to alter, or log, connection and execution parameters, or to further change python-oracledb functionality.
The example below demonstrates subclassing a connection to log SQL execution to a file. This example also shows how connection credentials can be embedded in the custom subclass, so application code does not need to supply them.
class Connection(oracledb.Connection): log_file_name = "log.txt"
def __init__(self):
connect_string = "hr/hr_password@dbhost.example.com/orclpdb"
self._log("Connect to the database")
return super(Connection, self).__init__(connect_string)
def _log(self, message):
with open(self.log_file_name, "a") as f:
print(message, file=f)
def execute(self, sql, parameters):
self._log(sql)
cursor = self.cursor()
try:
return cursor.execute(sql, parameters)
except oracledb.Error as e:
error_obj, = e.args
self._log(error_obj.message)
raise
connection = Connection() connection.execute(""" select department_name from departments where department_id = :id""", dict(id=270))
The messages logged in log.txt
are:
Connect to the database
select department_name
from departments
where department_id = :id
If an error occurs, perhaps due to a missing table, the log file would contain instead:
Connect to the database
select department_name
from departments
where department_id = :id
ORA-00942: table or view does not exist
In production applications, be careful not to log sensitive information.
See Subclassing.py for an example.
25.2. Python-oracledb Plugins
Plugins simplify extending python-oracledb functionality, and optionally allow the distribution of such extensions as modules. The plugin mechanism provides a loose coupling for python-oracledb, permitting different python-oracledb configurations.
Examples are the pre-supplied plugins for Centralized Configuration Providers. The loose coupling allows these plugins to be included with all python-oracledb installations but the large Python SDK modules used by the plugins are not installed as python-oracledb dependencies. Only users who want to use a specific configuration provider plugin need to install its required SDK.
All python-oracledb installations bundle the following plugins:
oci_config_provider
which allows connection and pool creation calls to access connection configuration information stored in OCI Object Storage. SeeUsing an OCI Object Storage Centralized Configuration Provider.azure_config_provider
which allows connection and pool creation calls to access connection configuration information stored using Azure App Configuration. See Using an Azure App Centralized Configuration Provider.oci_tokens
which uses the Oracle Cloud Infrastructure (OCI) Software Development Kit (SDK) to generate access tokens when authenticating with OCI Identity and Access Management (IAM) token-based authentication. SeeOCI Cloud Native Authentication with the oci_tokens Plugin.azure_tokens
which uses the Microsoft Authentication Library (MSAL) to generate access tokens when authenticating with OAuth 2.0 token-based authentication. See Azure Cloud Native Authentication with the azure_tokens Plugin.
To import these python-oracledb plugins in your application, useimport oracledb.plugins.<name of plugin>
, for example:
import oracledb.plugins.oci_tokens
Note that the namespace oracledb.plugins.ldap_support
is reserved for future use by the python-oracledb project.
25.2.1. Building Custom Plugins
If you want to use the plugin mechanism for your own packages, you can create a namespace package. You can distribute plugin packages either internally within your organization, or on a package repository such as PyPI.
The following example creates a plugin that uses a connection protocol hook function to do special processing of connection strings prefixed with “myprefix://”.
- In a terminal or IDE, create a working directory, for example
myplugin
. Inside the working directory create the subdirectory hierarchysrc/oracledb/plugins/
:
mkdir myplugin
mkdir -p myplugin/src/oracledb/plugins - In the
myplugin
directory, create the following files:- A
README
file:
My sample connection plugin. - A
pyproject.toml
file:
[build-system]
requires = ["setuptools"]
build-backend = "setuptools.build_meta" - A
setup.cfg
file:
[metadata]
name = myplugin
version = 1.0.0
description = Sample connection plugin for python-oracleb
long_description = file: README
long_description_content_type = text/markdown
author = Your Name
author_email = youremail@example.com
license = Apache Software License
[options]
zip_safe = False
package_dir =
=src
[options.packages.find]
where = src
- A
- Create the plugin code in
myplugin/src/oracledb/plugins/myplugin.py
:
import oracledb
def myhookfunc(protocol, arg, params): print(f"In myhookfunc: protocol={protocol} arg={arg}") params.parse_connect_string(arg)
oracledb.register_protocol("myprefix", myhookfunc)
- Build the sample package:
cd myplugin
python -m pip install build
python -m build - Install the sample package:
python -m pip install dist/myplugin-1.0.0-py3-none-any.whl - To show the plugin being used, create an application file containing:
import oracledb
import oracledb.plugins.myplugin
cs = 'myprefix://localhost/orclpdb1'
cp = oracledb.ConnectParams()
cp.parse_connect_string(cs)
print(f"host={cp.host}, port={cp.port}, service name={cp.service_name}")
Running this will print:
In myhookfunc: protocol=myprefix arg=localhost/orclpdb1
host=localhost, port=1521, service name=orclpdb1 - To uninstall the plugin, simply remove the package:
python -m pip uninstall myplugin
25.3. Connection Hooks
Connection hooks allow you to modify the connection logic based on your needs. The hooks supported by python-oracledb are listed in this section.
25.3.1. Connection Protocol Hooks
The oracledb.register_protocol() method registers a user protocol hook function that can be called internally by python-oracledb prior to connection or pool creation.
See Using Protocol Hook Functions for usage information.
25.3.2. Connection Password Hooks
The oracledb.register_password_type() method registers a user password hook function that will be called internally by python-oracledb prior to connection or pool creation.
See Using Password Hook Functions for usage information.
25.3.3. Connection Parameter Hooks
The oracledb.register_params_hook() method registers a user parameter hook function that will be called internally by python-oracledb prior to connection or pool creation.
See Using Parameter Hook Functions for usage information.