Happy Friday, and welcome back to Thank Goodness It’s FME! This week, Carl will be discussing a method for writing data to the legacy Esri Personal Geodatabase (PGDB) format in a modern FME workspace.
You may be wondering, why are we even talking about this format in 2026? After all, the PGDB has been on its way out for the better part of two decades. At first, this decline in popularity was due to inherent limitations to the format: a personal geodatabase .mdb file is really a Microsoft Access database with spatial extensions, which means it inherits Access's constraints, including a hard 2 GB ceiling and a dependency on the 32-bit Microsoft Jet engine. Twenty years ago, Esri introduced the file geodatabase we all know and love with ArcGIS 9.2 specifically to move past those limits, and the industry has been slowly migrating away from the PGDB format ever since. More recently, the broader shift to 64-bit applications has accelerated the deprecation of the format: personal geodatabases are not supported in 64-bit Esri applications, and ArcMap, the primary application for creating and writing to the PGDB format, has been retired.
Nonetheless, the PGDB format lives on. It is not uncommon for data submission specifications to outlive the software that they were written for, and many organizations - including government ministries, natural resource agencies, and utility providers - continue to maintain delivery specs that were drafted when ArcMap and PGDB were the industry standard. If you are a contractor delivering to one of these recipients, the format of your deliverable is often non-negotiable, which means you now need to find a way to integrate PGDB writing into your FME workspace.
And that brings us to the topic of this week’s TGIF: While it is still possible to read a PGDB into a workspace, the ability to create new PGDB .mdb files and write data to them has been deprecated since FME 2022.0. This wasn't a decision about the PGDB format specifically. FME's PGDB writer was built on 32-bit ArcObjects, and FME 2021.2 was the last release to ship with 32-bit Windows support. When FME went 64-bit only in 2022.0, the writer had nothing left to run on.
However, with some creative PythonCaller scripting (and a local installation of ArcMap), we can bring PGDB writing back into a modern FME workspace.
The core idea: let the legacy code run somewhere else
ArcMap's arcpy can still create and write to PGDBs, so the obvious move would be to drop a PythonCaller into the workspace and call it directly.
Unfortunately, that doesn’t work, and understanding this limitation is key to understanding why the following method is necessary: ArcMap’s version of arcpy is 32-bit Python 2.7, FME is 64-bit Python 3.x, and PythonCaller scripts run inside FME’s process using FME’s Python interpreter. This fundamental incompatibility prevents us from importing ArcMap’s arcpy in current versions of FME.
What we can do is use PythonCaller to launch a subprocess that runs a conversion script using ArcMap’s Python 2.7 outside of FME. This works because subprocesses utilize their own interpreters and memory space - nothing from Python 2.7 is ever loaded into FME, completely sidestepping the aforementioned compatibility issues.
This method uses three transformers:
- FeatureWriter: Writes data to an intermediate format. In this example we will be writing to a File Geodatabase. This intermediate format is required for the data to cross the process boundary from Python 3.x (FME) to Python 2.7 (ArcMap).
- AttributeManager: Builds the command that the PythonCaller will run. We create four new attributes - the path to ArcMap’s Python interpreter, the path to our conversion script, the output folder for the PGDB, and the filename for the PGDB. We will also use FeatureWriter’s built-in _dataset attribute in the script as the path to our intermediate data.
- PythonCaller: Assembles the attributes into a command line and executes the subprocess. This launches ArcMap’s Python 2.7 as an entirely separate process, waits to finish, and then checks the exit code to confirm that the conversion was successful.

First things first, we need to save our conversion script
The subprocess script: convert.py
The following script is intended for converting File Geodatabases to Personal Geodatabases, but it should also work with shapefiles as the input. With a bit of tweaking it can also be adapted to GeoJSON or CSV input data.
The convert.py script takes three arguments: the intermediate file geodatabase fgdb, the output folder out_folder, and the output name out_name.
# convert.py - runs under ArcMap's 32-bit Python 2.7
import os, sys, traceback
import arcpy
def main(fgdb, out_folder, out_name):
out_mdb = os.path.join(out_folder, out_name)
if arcpy.Exists(out_mdb):
arcpy.Delete_management(out_mdb)
arcpy.CreatePersonalGDB_management(out_folder, out_name, "10.0")
arcpy.env.workspace = fgdb
arcpy.env.overwriteOutput = True
fcs = arcpy.ListFeatureClasses() or []
if not fcs:
raise RuntimeError("No feature classes found in %s" % fgdb)
arcpy.FeatureClassToGeodatabase_conversion(fcs, out_mdb)
print("Wrote %d feature class(es) to %s" % (len(fcs), out_mdb))
if __name__ == "__main__":
try:
main(sys.argv[1], sys.argv[2], sys.argv[3])
sys.exit(0)
except Exception:
traceback.print_exc(file=sys.stderr)
sys.exit(1)
Save this script locally and note the filepath - in the workspace, we will use AttributeManager to assign this path as a value.
Putting it all together
The workspace is straightforward: Write the data to the intermediate file geodatabase with FeatureWriter, build the arguments with AttributeManager, and configure PythonCaller to run the convert.py subprocess.

- FeatureWriter: We use FeatureWriter to write the intermediate data because it allows us to chain additional transformers downstream without ending the translation. Nothing special here - just write the file geodatabase as normal and attach an AttributeManager to the Summary port.
- AttributeManager: We will create four new attributes using absolute paths.
| Attribute | Example Value | Description |
| arcpy_exe | C:/Python27/ArcGIS10.8/python.exe | ArcMap python.exe path |
| convert_script | C:/Scripts/convert.py | convert.py path |
| out_folder | C:/Output | Output folder path |
| out_name | points.mdb | Output filename + extension |
- PythonCaller: Replace the default script with the following, and add conv_rc, conv_out and conv_err under Attributes to Expose.
import os
import subprocess
from fme import BaseTransformer
import fmeobjects
class FeatureProcessor(BaseTransformer):
def __init__(self):
pass
def input(self, feature):
args = [feature.getAttribute('arcpy_exe'),
feature.getAttribute('convert_script'),
feature.getAttribute('_dataset'),
feature.getAttribute('out_folder'),
feature.getAttribute('out_name')]
if not all(args):
raise fmeobjects.FMEException(
"Missing attribute - check the AttributeManager: %s" % args)
proc = subprocess.run(args, capture_output=True, text=True,
errors='replace', timeout=600)
feature.setAttribute('conv_rc', str(proc.returncode))
feature.setAttribute('conv_out', proc.stdout)
feature.setAttribute('conv_err', proc.stderr[-2000:])
if proc.returncode != 0:
raise fmeobjects.FMEException("Conversion failed: " + proc.stderr)
self.pyoutput(feature)
def close(self):
pass
A few caveats
This is a viable method for writing data to PGDB format in modern versions of FME, but it is important to remain aware of its dependencies:
- ArcMap is the load-bearing tool in this process, and it has been retired by Esri. This method will only remain viable as long as an installation of ArcMap remains installed and licensed.
- Ensure that the intermediate data is formatted for ArcMap. 64-bit Object IDs and newer ArcGIS Pro field types will not be compatible.
- Don’t forget the limitations of the PGDB format! While .mdb files have a hard ceiling of 2 GB, Esri’s guidance states that the effective size for personal geodatabases is between 250 and 500 MB - anything beyond that will begin to introduce performance issues.
The bigger picture
Writing to the personal geodatabase format from FME is a very specific problem with a limited shelf life, but the pattern behind this method isn’t. Any time FME needs to reach a tool it can’t load in-process, such as legacy command line utilities or incompatible Python environments, the same pattern behind this method can be applied in any workspace: Write to an intermediate with FeatureWriter, define the necessary arguments in AttributeManager, and then launch a subprocess using PythonCaller.
Have you used FME to build similar bridges to a legacy tool? We’d be curious to hear what you were up against - drop a comment below, and we’ll see you next Friday!

