Engines¶
PyAccessKit uses DAO for all schema and data work, and Microsoft Access (Access.Application) for design
work: forms, modules, and SaveAsText/LoadFromText. DAO can be reached in three ways, and the choice
matters for bitness, licensing and safety.
Transport (db.transport) |
How | Good for | Caveats |
|---|---|---|---|
dao-inproc |
DAO.DBEngine.120 loaded into Python |
Fastest. No MSACCESS.EXE. Works with only the Access Runtime installed. |
Python and Office must have the same bitness |
access-hosted |
A hidden Access instance owned by PyAccessKit hosts DAO; the database is opened with DBEngine.OpenDatabase |
Any bitness combination. The database is not opened in the Access UI, so startup code never runs. | Starts one MSACCESS.EXE per session |
access-design |
The database is Access's current database (OpenCurrentDatabase) |
Forms, modules, text import/export | Needs full Access, not the Runtime. Startup code is governed by macro_security. |
Choosing an engine¶
AccessDatabase.open("app.accdb") # engine="auto" (default)
AccessDatabase.open("app.accdb", engine="dao") # in-process DAO only; never starts Access
AccessDatabase.open("app.accdb", engine="access") # always through Microsoft Access
autouses in-process DAO when this Python can load it, and Microsoft Access otherwise. The first design feature (a form, a module, text I/O,db.raw.access) switches the session to a design session.daonever starts Access. Design features raiseCapabilityError. If DAO cannot be loaded, the session raisesDaoNotAvailableErrorwith an explanation such as "DAO is installed for 32-bit programs only, but this Python is 64-bit".accessalways goes through an owned Access instance, using Access-hosted DAO for schema work until a design feature needs a design session.
The switch to a design session¶
When a session switches engines, PyAccessKit releases the in-process DAO connection, starts (or reuses) its own Access instance, and opens the database as the current database. Two consequences:
- Handles keep working.
db.tables["Customers"]holds only a name, so it is valid after the switch. - Raw objects are revoked. A
db.raw.daoobtained before the switch raisesSessionClosedError. Get a fresh one afterwards.
Read-only sessions cannot switch: opening a database for design needs exclusive, writable access.
Capabilities¶
| Capability | In-process DAO | Access-hosted DAO | Design session |
|---|---|---|---|
| Create / open / close | ✅ | ✅ | ✅ |
| Tables, fields, indexes, field properties | ✅ | ✅ | ✅ |
| Decimal columns | ✅ (ADO + ACE OLEDB) | switches to design | ✅ (CurrentProject.Connection) |
| Relationships, saved and pass-through queries, execute/fetch | ✅ | ✅ | ✅ |
| List forms, reports, macros and modules | ✅ | ✅ | ✅ |
| Create or modify forms and modules; text import/export | ❌ | switches to design | ✅ |
| Runs the database's startup code | never | never | per macro_security (off by default) |
Bitness¶
| Python | Office / Access Runtime | In-process DAO | Access transports |
|---|---|---|---|
| 64-bit | 64-bit | ✅ | ✅ |
| 32-bit | 32-bit | ✅ | ✅ |
| 64-bit | 32-bit | ❌ | ✅ |
| 32-bit | 64-bit | ❌ | ✅ |
Microsoft 365 is often installed as 32-bit, while Python installers default to 64-bit. PyAccessKit works in
that combination through Access. For in-process speed, add a matching Python, for example
uv python install cpython-3.12-windows-x86.
Same result from every engine¶
DAO's CreateDatabase and Access's NewCurrentDatabase write slightly different database properties.
When DAO creates a database, PyAccessKit adds the properties Access itself writes (tabbed documents, and so
on). A database looks the same in Access whichever engine created it. To disable this, set
SessionOptions(apply_native_defaults=False).