Skip to content

Migrate from IfxPy

If you have working IfxPy code, migration is mostly mechanical. Both drivers are PEP 249 with similar shapes; the differences are in connection construction, a few cursor extensions, and async support.

# IfxPy
import IfxPy
conn_str = (
"DATABASE=mydb;HOSTNAME=db.example.com;PORT=9088;"
"PROTOCOL=onsoctcp;UID=informix;PWD=...;SERVICE=informix"
)
conn = IfxPy.connect(conn_str, "", "")
# informix-driver
import informix_db
conn = informix_db.connect(
host="db.example.com", port=9088,
user="informix", password="...",
database="mydb", server="informix",
)

The informix-driver keyword-argument form is closer to psycopg/asyncpg shapes. Connection strings aren’t supported (deliberately — they’re a security and parsing footgun).

cursor(), execute(), fetchone(), fetchmany(), fetchall(), executemany(), description, rowcount, close() — all behave per PEP 249.

The exception hierarchy is identical: Error, Warning, InterfaceError, DatabaseError, DataError, OperationalError, IntegrityError, InternalError, ProgrammingError, NotSupportedError.

  • Named-parameter callproc. We have fast_path_call for direct UDF/SPL invocation but the API shape differs.
  • IBM-specific scrollable cursor extensions. We support PEP 249 scrollable cursors (scroll(value, mode)) but not IfxPy’s last/prior/relative shortcuts.
  • cursor.set_chunk_size. We tune fetch behavior via the buffered reader; no per-cursor knob.
  • Async API (from informix_db import aio)
  • Connection pool (informix_db.create_pool / aio.create_pool)
  • Type-safe annotationsinformix-driver ships with py.typed
  • Python 3.12+ support
  • Pipelined executemany — 1.6× faster than IfxPy’s per-row implementation

If your codebase has hundreds of IfxPy call sites, you can do a partial migration:

  1. Replace connection construction with informix-driver at the application boundary.
  2. Where you used IfxPy.fetch_assoc (returns dict), wrap our cursor with a small adapter:
    def fetch_assoc(cur):
    row = cur.fetchone()
    if row is None:
    return False
    return dict(zip([c[0] for c in cur.description], row))
  3. For IfxPy.exec_immediate, use cur.execute(sql) with no params.
  4. For IfxPy.bind_param, use the params arg of execute(): cur.execute(sql, (a, b, c)).

Most application code can be migrated with sed-level transformations.