Python sample¶
The SIDRA API is a .NET 8 assembly. From Python the supported path is
Python.NET (pythonnet), which loads the
assembly straight into the CLR and exposes its types as Python objects. This
is not COM: there is no pywin32, no win32com.client.Dispatch, and no
COM registration involved.
This sample opens a SIDRA project, processes every site, and prints its level of service and degree of saturation.
Note
Complete the Getting started prerequisites first
(SIDRA Intersection installed, .NET 8). You also need a SIDRA project
(.sipx) file to open. Save one from SIDRA Intersection, or point the
sample at any existing project. Replace C:\Samples\Demo.sipx below with
its path. If anything fails, see Troubleshooting.
1. Install Python.NET¶
Important
Use 64-bit Python. The SIDRA API is net8.0-windows x64-only and will fail
to load into a 32-bit interpreter.
Note
The API targets .NET 8, so Python.NET must host the CoreCLR runtime, not
.NET Framework. Select it before the first import clr (see
Selecting the runtime).
2. Write the program¶
first_program.py:
import os
import winreg
from pythonnet import set_runtime
from clr_loader import get_coreclr
def sidra_install_path():
"""Read the SIDRA Intersection install folder from the registry."""
key = r"SOFTWARE\SIDRA SOLUTIONS\SIDRA INTERSECTION 11"
with winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, key) as k:
return winreg.QueryValueEx(k, "InstallLocation")[0]
sidra = sidra_install_path()
# Host the API's own .NET 8 runtime (via its runtimeconfig), then load the DLL.
# This must happen before the first `import clr`.
set_runtime(get_coreclr(
runtime_config=os.path.join(sidra, "SIDRASolutions.SI.API.runtimeconfig.json")))
import clr
clr.AddReference(os.path.join(sidra, "SIDRASolutions.SI.API.dll"))
from SIDRASolutions.SI.API import SIAPI
api = SIAPI()
try:
if not api.OpenProject(r"C:\Samples\Demo.sipx"):
raise RuntimeError(f"Could not open project: {api.LastErrorMessage}")
project = api.Project
print(f"Project: {project.Name}")
# Project -> SiteFolders -> Sites. In SIDRA a "site" is an intersection.
# .NET indexers map to Python subscripting, so use [] (not COM-style ()).
folders = project.SiteFolders
for f in range(folders.Count):
sites = folders[f].Sites
for s in range(sites.Count):
site = sites[s]
site.Process() # run the analysis for this site
# Site-level vehicle results live under Outputset.OutputSiteVehicle.
result = site.Outputset.OutputSiteVehicle
print(f" {site.Name}: LOS {result.Level_of_service}, "
f"degree of saturation {result.Deg_satn:.3f}")
finally:
api.Close() # shuts down the SIDRA runtime
3. Run it¶
Expected output (values depend on your project):
Project: Demo
North Rd / Main St: LOS B, degree of saturation 0.742
East Ave / Main St: LOS C, degree of saturation 0.871
Selecting the runtime¶
Python.NET 3.x can host either .NET Framework or .NET (CoreCLR), and on Windows
it may default to .NET Framework. The SIDRA API is .NET 8, so you must host
CoreCLR. Passing the API's own SIDRASolutions.SI.API.runtimeconfig.json to
get_coreclr(...) and calling set_runtime(...) before the first import clr
(as above) selects the correct .NET 8 runtime and the dependencies the API was
built against.
Python.NET also needs a .NET 8 runtime present on the machine. The SIDRA Intersection installer satisfies this; otherwise install the .NET 8 Desktop Runtime.
Locating the assembly¶
The install folder holds SIDRASolutions.SI.API.dll alongside its
SIDRASolutions.SI.API.runtimeconfig.json. The sample reads that folder from
the registry value
HKLM\SOFTWARE\SIDRA SOLUTIONS\SIDRA INTERSECTION 11\InstallLocation, which
avoids hard-coding a path. You can also pass the folder explicitly, then load
the assembly by full path with
clr.AddReference(os.path.join(folder, "SIDRASolutions.SI.API.dll")).
Working with .NET types¶
Because Python.NET binds the managed types directly, you get the real
SIDRASolutions.SI.API classes rather than a late-bound COM wrapper.
Interfaces such as ISIAPIProject
and their members surface as ordinary Python attributes, collection indexers
are accessed with [], and .NET enums import from the same namespace.