Open Source Python Thin Driver for Oracle Database
A new major Python cx_Oracle driver release is available and comes with a brand new name, python-oracledb. This is very exciting news.

Python-oracledb 1.0 is the upgrade from Oracle’s very popular Python driver cx_Oracle 8.3, used by Python applications to connect to Oracle Database.
The new release introduces significant new functionality. By default, it is now a Thin driver that doesn’t need Oracle Client libraries. This lets python-oracledb be used when Oracle Client libraries are unavailable (such as Apple M1, Alpine Linux, or IoT devices), or when the client libraries are not easily installed (such as some cloud environments). You can, of course, easily connect to Oracle Database from many other environments, including our favorite Oracle Linux. (Update: Instant Client for Apple Silicon is now available).
The cx_Oracle driver project was begun in 1998 by Anthony Tuininga for Python 1.5 and Oracle 8i. (Factoid: the “cx” in the name is an abbreviation of the company he then worked for). A lot has happened in the Python and Oracle worlds since then — including Anthony joining Oracle. He, and Oracle Database’s driver team, have now invested deeply in modernizing the driver to bring you this major release. My thanks to everyone involved and to the Oracle community members who use and contribute to cx_Oracle. I’m sure you will continue to embrace and use the driver as it continues to evolve. It’s been an exciting journey to bring the elegance of the new release to you — an elegance we love.
A video discussing the introduction of python-oracledb is available here.
PYTHON-ORACLEDB NEED TO KNOW
- Python-oracledb is the new name for our popular cx_Oracle driver.
- Simple and small to install — under 15 MB (including its Python package dependencies):
pip install oracledb
- The driver is now a Thin driver by default, meaning it is lightweight and doesn’t require additional Oracle libraries. We don’t commonly refer to it as a ‘native driver’ because that term has different meanings for different people — however it is a compiled driver, native to the OS which gives it great performance. Pre-built binaries for popular operating systems and python versions are part of the package installed.
- By default it doesn’t need Oracle Client libraries so you can use it on many platforms, even on some that don’t have Oracle Client libraries available.
- It has comprehensive functionality conforming to the Python Database API v2.0 Specification, with many additions and just a couple of exclusions.
- A “Thick” mode can be optionally enabled by an application call. This mode has similar functionality to cx_Oracle and supports Oracle Database features that extend the Python DB API. To use this mode, the widely used and tested Oracle Client libraries such as from Oracle Instant Client must be installed separately.
- SQLAlchemy, Pandas, Django and other frameworks and libraries can immediately use python-oracledb in Thin or Thick mode by adding several lines of name mapping code. This won’t be necessary in future when framework and ORM maintainers add equivalent code to use the new namespace. (Update: direct support for the new namespace has been added to SQLAlchemy 2.0 and Django 5.0).
PYTHON-ORACLEDB QUICKSTART
Install from PyPi:
python -m pip install oracledb
In text and URLs we refer to the driver as “python-oracledb” to help identify it, but in Python code the module itself is simply “oracledb”.
Applications use the familiar Python DB API:
import oracledb
connection = oracledb.connect(user='scott', password=mypw, dsn='localhost/oraclepdb1')
with connection.cursor() as cursor:
for row in cursor.execute('select city from locations'):
print(row)
Note that oracledb.connect()
requires named "keyword" parameters, conforming to the Python DB API specification.
See the installation instructions for more details.
UPGRADING TO PYTHON-ORACLEDB FROM CX_ORACLE
To upgrade existing cx_Oracle code to python-oracledb:
1. Install the new module:
python -m pip install oracledb
2. Import the new interface module:
import oracledb as cx_Oracle
3. Make sure to use named parameters in calls to connect()
, Connection()
, and SessionPool()
.
For example, this:
c = cx_Oracle.connect("un", "pw", "cs")
needs to be changed to:
c = cx_Oracle.connect(user="un", password="pw", dsn="cs")
or do the following (though I don’t recommend this if you want to use “/” or “@” in your password):
c = cx_Oracle.connect("un/pw@cs")
This conforms to the Python DB API specification.
4. Remove calls to init_oracle_client()
since this will turn on Thick mode - unless you want to use Thick mode, of course. In that case you will need to add a call to init_oracle_client()
.
See the documentation Upgrading from cx_Oracle 8.3 to python-oracledb for more details. Also see the blog post Upgrade your Python apps from cx_Oracle 8 to python-oracledb.
OTHER NEW FEATURES
A significant amount of engineering focus was on the ‘Thin’ mode, but some other great functionality lands in python-oracledb 1.0 on top of the cx_Oracle 8.3 feature set. The features include some big and some small:
- Code annotations for intelligent IDE code completion. This is thanks to a new top driver layer written in Python.
- macOS Universal 2 binaries that run on Apple’s Intel and M1 chipsets. Update: Linux ARM binaries are also now available.
- A new
oracledb.defaults
object for setting some common, application-wide defaults. For example the attributeoracledb.defaults.fetch_lobs
can be set toFalse
so that LOBs are fetched strings or bytes instead of LOB objects. This removes the need to implement an output type handler. - New ConnectParams and PoolParams classes that can be passed to connection creation and pool creation functions respectively. These make it easier to encapsulate connection and connection pool settings.
- Connection pools using DRCP connections can specify the ‘connection class’ and ‘purity’ during Connection pool creation. This makes it easier to define the application behavior during initialization.
- Two-phase commit (TPC) support. A brand new API for TPC makes distributed transactions easy.
- Advanced Queuing (AQ) now supports recipients lists.
- Statements can be excluded from the statement cache so that an infrequently run statement won’t push out a frequently used one
- More useful error messages in significant places, including during connection and for data binding.
- The
_Error
class now contains afull_code
attribute containing the error prefix and number, e.g. ‘ORA-01476’ - The
oracledb.init_oracle_client()
function may be called multiple times in each process, removing the need for the application to enforce only a single call. - A light-weight
connection.is_healthy()
method was added similar toconnection.ping()
but without performing the full round-trip validation to the database.
See the Release Notes for more enhancements.
PERFORMANCE
We are very happy with the performance characteristics of python-oracledb’s Thin mode.
Looking at some atomic tests results where we fetched 50,000 rows with 9 columns of the given type, using the default arraysize
value:
- VARCHAR2 columns: python-oracledb Thin mode is 12% faster (elapsed time) and takes 23% less CPU than cx_Oracle
- NUMBER columns: python-oracledb Thin mode is 19% faster (elapsed time) and takes 25% less CPU than cx_Oracle
To do bulk inserts with executemany()
inserting 500,000 rows with 10 columns, doing the insert in 5 batches of 100,000 rows each (i.e calling executemany()
5 times):
- VARCHAR2 columns: python-oracledb Thin mode is 40% faster and uses 48% less CPU than cx_Oracle
- NUMBER columns: python-oracledb Thin mode is 28% faster and uses 15% less CPU than cx_Oracle
The Thick mode numbers are closer to cx_Oracle, which is expected since they are the same architecture. We will continue to work on improving performance. Update: check out this post: Python-oracledb Thin mode Object performance.
Note since there was some refactoring from the cx_Oracle code, the runtime performance and load profile of some existing applications may change in python-oracledb, depending on your application. One effect is due to Python’s infamous GIL. (The Python community project to remove the GIL may not land in Python 3.11, but there are other performance improvements already in).
FUTURES
Just as we did under the previous cx_Oracle namespace, we will continue to enhance and maintain python-oracledb. We already have a long wish list, particularly for Thin mode enhancements. One item on that list is support for AsyncIO, which has been a common request. Now we have a Thin mode this becomes feasible, although not trivial. (Update: support for AyncIO landed in python-oracledb 2.0. Support for Pipelining landed in python-oracledb 2.4)
Under the cx_Oracle namespace, bug fix releases and binary packages to support new Python versions will continue for a limited time, circa two years. A final sunset date will be decided later, depending on feedback from you. We know many of you have large code bases that you will want to evaluate with the upgraded driver before moving to it. Or you might choose to use python-oracledb only for new projects. Support for any particularly critical new Oracle Database features may also possibly land in cx_Oracle, but nothing is on the radar. (Update: see the more recent post What is the difference between cx_Oracle and python-oracledb?)
You have all successfully navigated major cx_Oracle releases before, and this release is no different: there are great new features, a few small changes, and a few deprecations.
Let us know about your experiences with python-oracledb by email, or by posting on the GitHub discussions page. We’d love to hear from you.
RESOURCES
Home page: oracle.github.io/python-oracledb
Installation instructions: python-oracledb.readthedocs.io/en/latest/installation.html
Documentation: python-oracledb.readthedocs.io
Questions: github.com/oracle/python-oracledb/discussions
Source Code Repository: github.com/oracle/python-oracledb