[SQLAlchemy] Fixing the DPI-1047 Python Oracle DB Connection Error on AWS Graviton (ARM) | SQLAlchemy, oracledb

1. The issue when changing to AWS EC2 ARM architecture

Recently, more companies are switching to the cost-effective AWS Graviton (ARM/aarch64) instances. But if you move Python code that worked fine on the existing x86_64 environment as-is, you'll run into the DPI-1047 error when integrating with Oracle DB.

I want to organize the fundamental cause of this error and a complete solution using the latest driver, python-oracledb.

2. What is the DPI-1047 error?

This error, which occurs when connecting via SQLAlchemy or cx_Oracle, means "the Oracle Client library cannot be located."

sqlalchemy.exc.DatabaseError: (cx_Oracle.DatabaseError) DPI-1047: Cannot locate a 64-bit Oracle Client library:
"libclntsh.so: cannot open shared object file: No such file or directory".

3. (Cause) Why does it happen only on ARM servers?

This problem occurs because of a mismatch between the server CPU architecture and the library.

  • cx_Oracle's dependency: the existing cx_Oracle driver only works if the C-based Oracle Instant Client library is installed on the system. (This way of integrating by installing the Client is called Thick mode.)
  • Architecture mismatch: Oracle long did not officially support the Instant Client library for ARM (aarch64), or the setup was very tricky. In the end, trying to load an x86_64-only library on an ARM environment, the system doesn't recognize it — that's the architecture-mismatch problem.

(Beyond CPU architecture, Oracle DB also depends on various versions when installing — for example, RHEL or CentOS-based is much more convenient than Ubuntu. In my experience, Oracle DB was heavily affected by environmental factors.)

4. The fix: python-oracledb 'Thin' mode

The DPI-1047 error on an AWS Graviton ARM instance and python-oracledb Thin mode Figure 1. The DPI-1047 error on an AWS Graviton ARM instance and python-oracledb Thin mode

To solve this architecture problem, Oracle released python-oracledb, the successor to cx_Oracle. In particular, this driver's Thin mode is an essential element when operating a Python server on an ARM server. (The way of integrating within the library itself, without needing the Instant Client, is called Thin mode.)

  • No Instant Client needed: rewritten in 100% pure Python with no C library dependency.
  • Architecture Agnostic: doesn't depend on the architecture. It works the same whether x86 or ARM. (That's why these days ox_Oracle is hardly used and only oracledb is used.)
  • Direct communication: it talks to the DB directly via the Oracle Net Protocol, without going through system libraries.
Driver Characteristics Recommended environment SQLAlchemy URL scheme
cx_Oracle C library-based x86_64 (legacy) oracle+cx_oracle://
oracledb Thin mode support ARM(aarch64), Cloud oracle+oracledb://

4.1 SQLAlchemy example and setup

1. Install the library

pip install oracledb

2. Code implementation examples

2.1 SQLAlchemy URL integration

When using cx_Oracle, you can see it starts with oracle+cx_oracle:// as below.

# [x86_64 only / high chance of error on ARM]
# the way that hunts for the system's libclntsh.so file
SQLALCHEMY_DATABASE_URL = f"oracle+cx_oracle://{user}:{password}@{host}:{port}/?service_name={service_name}"

The oracledb way (the recommended way when integrating via a SQLAlchemy URL)

from sqlalchemy import create_engine

# Removing invisible whitespace when loading from JSON/env vars is a must.
user = db.get("user").strip()
password = db.get("password").strip()
host = db.get("host").strip()
port = db.get("port")
service_name = db.get("service_name").strip()

# Use the URL scheme for python-oracledb Thin mode
SQLALCHEMY_DATABASE_URL = f"oracle+oracledb://{user}:{password}@{host}:{port}/?service_name={service_name}"

engine = create_engine(SQLALCHEMY_DATABASE_URL)

# Connection test
with engine.connect() as conn:
    print("Connected to Oracle DB successfully on ARM(aarch64) server!")
💡 Tip: When loading info from a JSON or .env file, there were cases where the connection failed if invisible whitespace or a newline (\n) was included — for example, when the password ends with a special character like !. So I added strip() at the end.

2.2 Native integration (calling the Driver Library)

1. The cx_Oracle way (the traditional Thick mode way)

Because it depends on a C library, it needs a process of initializing the library path at the code level, and if the architecture doesn't match, the error blows up right here. (cx_Oracle way: complex initialization)

import cx_Oracle
import os

# you have to load the instantclinet
lib_dir = "/opt/oracle/instantclient_21_10"

try:
    # manual library initialization (a required process for Thick mode)
    cx_Oracle.init_oracle_client(lib_dir=lib_dir)
except Exception as e:
    print(f"Library load failed (DPI-1047 raised): {e}")

# connection info
dsn = cx_Oracle.makedsn("host", 1521, service_name="sn")
conn = cx_Oracle.connect(user="user", password="password", dsn=dsn)

2. python-oracledb (the latest Thin mode way) - (the recommended way)

You don't even need to specify a library path at all. It works with pure Python code regardless of architecture.

import oracledb

try:
    # connect right away with no separate setup (Thin mode is the default)
    conn = oracledb.connect(
        user="user",
        password="password",
        host="host",
        port=1521,
        service_name="sn"
    )
    print("Connected in Thin mode!")
except Exception as e:
    print(f"Connection failed: {e}")

As you can see, cx_Oracle has the hassle of having to directly call the Oracle Client library installed on the system, but python-oracledb omits that process entirely. When using the oracledb driver, no separate library initialization process (init_oracle_client) is needed at all, and it can run immediately regardless of x86 or ARM architecture.

When using AWS EC2 with the ARM architecture, the python-oracledb driver is an essential element for Python–Oracle DB integration.


📦 Migrated from the Tistory blog I used to run. Original: taehyuklee.tistory.com/32

Share𝕏f

Comments