IronPython 3: a Python 3.4 implementation inside .NET, and what it costs you
Implementation of Python 3.x for .NET Framework that is built on top of the Dynamic Language Runtime.
At a glance
- What is it?
- IronPython 3 runs Python on the Dynamic Language Runtime so .NET and Python code can call each other. It targets Python 3.4, and its own README says much work remains.
- Who is it for?
- Adopt IronPython 3 when the Python code has to live inside a .NET process or the script has to reach .NET types directly, and when Python 3.4 level is enough. Do not adopt it as a general CPython replacement, and do not expect current Python 3 syntax or the full standard library.
- Can I use it commercially?
- Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 8 days ago.
- What is it written in?
- Mainly C#, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 24, 2026, and from our analysis. They are not legal advice.
Editorial analysis
What problem IronPython 3 solves, and for whom
CPython is a C program. Getting it to share objects with a .NET runtime means a bridge layer, marshalling rules and a second runtime in the process. IronPython 3 removes the bridge by making the Python runtime itself a .NET library. The README states the goal plainly: IronPython can use .NET and Python libraries, and other .NET languages can use Python code just as easily.
The audience is narrower than the phrase "Python implementation" suggests. It is .NET developers who want scripting inside an application, test engineers who want to drive .NET assemblies from a short script, and teams with existing IronPython 2 automation that need to move to Python 3 syntax. The README's own example shows the intended shape: a Windows Forms MessageBox call written in Python with import clr, rather than a C# program that shells out to a Python process.
The README also states the project's honest position: "There is still much that needs to be done to support Python 3.x. We are working on it, albeit slowly." Treat that sentence as the headline, not the footnote.
How the Dynamic Language Runtime hosts Python
IronPython 3 is built on the Dynamic Language Runtime, which the README names in the project description. The DLR is the layer that lets a dynamic language compile to .NET expression trees and participate in the CLR's call sites. IronPython supplies the Python front end: parser, compiler and the object model that maps Python types onto .NET types.
The bridge is the clr module. Importing it and calling clr.AddReference loads a .NET assembly into the engine's search paths so that from System.Windows.Forms import MessageBox resolves. The reverse direction is the hosting API. Python.CreateEngine returns an engine, CreateScope gives it a namespace, Execute runs a source string in that scope, and GetVariable pulls a Python function back out as a dynamic object that C# can call. That is the whole data flow: source text in, a scope of Python objects out, and .NET types visible on both sides.
One consequence is worth stating. Because the engine is a library, the host decides where Python looks for modules. The PowerShell example in the README has to add the lib and lib/site-packages directories to the engine's search paths by hand, and adds the DLLs directory separately for wpf and sqlite3. A standalone interpreter build wires those paths up for you; an embedded engine does not.
Installing IronPython 3 and running a first script
The README points at the release page for .msi, .zip, .deb and .pkg binaries, and at NuGet for the IronPython package. The wiki page linked from Installation covers standalone interpreter setup on different operating systems and .NET frameworks. The PowerShell path is the shortest one shown in the README: a one-liner that fetches Install-IronPython.ps1 from the main branch and installs into a directory you name.
& ([scriptblock]::Create((iwr `
-Uri 'https://raw.githubusercontent.com/IronLanguages/ironpython3/main/eng/scripts/Install-IronPython.ps1').Content)) `
-Path "~/ipyenv/v3.4.2"
# Optionally, ensure pip:
# & "~/ipyenv/v3.4.2/ipy" -m ensurepipAfter that, the README shows entering the environment and running a one-liner. The output should be the greeting printed by the interpreter.
& "~/ipyenv/v3.4.2/Enter-IronPythonEnvironment.ps1"
ipy -c "print('Hello from IronPython!')"For embedding, the README imports IronPython.dll as a PowerShell module and creates an engine. Note the comment in that script: IronPython uses PowerShell's installation path by default, so the search paths have to be set explicitly before Execute is called.
Import-Module "~/ipyenv/v3.4.2/IronPython.dll"
$engine = & {
$engine = [IronPython.Hosting.Python]::CreateEngine()
$paths = $engine.GetSearchPaths()
$paths.Add("$(Resolve-Path "~/ipyenv/v3.4.2/lib")")
$paths.Add("$(Resolve-Path "~/ipyenv/v3.4.2/lib/site-packages")")
$paths.Add("$(Resolve-Path "~/ipyenv/v3.4.2/DLLs")")
$engine.SetSearchPaths($paths)
$engine.Execute("print('Hello from IronPython!')")
return $engine
}On the C# side the README's example assumes IronPython has been added as a NuGet package. Creating an engine, executing a function definition and calling the result through dynamic is the pattern to copy.
Where IronPython 3 is the wrong choice
The target is Python 3.4. The README says features and behaviors from later versions may be included, and links What's New pages up to Python 3.6, but the stated target is 3.4. Code that relies on syntax or library behaviour introduced after that point is not guaranteed to work, and the project's own compatibility notes are the only reliable way to check a specific feature.
Package compatibility is the second wall. The README links a Package compatibility wiki page rather than claiming broad support, which is the correct signal: pure-Python packages are the likely candidates, and anything with a C extension has to be re-examined. If your dependency tree includes a compiled extension, plan on verifying it before you design around IronPython.
There are documented behavioural differences from CPython as well, collected on a Differences from CPython wiki page. Treat that page as required reading, not optional. A team that picks IronPython expecting drop-in CPython behaviour will spend its time filing differences rather than shipping.
Finally, the build notes matter for anyone outside Windows. The README says the main development is on Windows and that bugs on other platforms may be inadvertently introduced, with a request to report them. That is a maintenance statement about platform coverage, not a guarantee of parity.
IronPython 3 against pythonnet and CPython
The closest alternative for .NET developers is pythonnet, which the related searches pair with IronPython. The difference is architectural. pythonnet loads the CPython runtime into a .NET process and exposes it through a binding layer, so the Python you run is CPython and the version you get is whatever CPython you installed. IronPython is a separate implementation written in C# on the DLR, so there is no CPython runtime in the process at all. In exchange for that, IronPython's language level is whatever the project has implemented, currently Python 3.4, and the standard library is the one the project ships.
That trade-off decides most cases. If you need a modern CPython, numpy or any compiled extension, pythonnet is the direction to investigate. If you need Python code to run inside a .NET process with no second native runtime and no interop marshalling, IronPython is the design that matches. CPython itself is the answer when the Python code does not need .NET at all; running it as a subprocess is simpler than either embedding option.
PyPy appears in the same search space and solves a different problem. It is a faster Python implementation, not a .NET integration layer, and it does not put .NET types in your Python namespace.
Maintenance, releases and upgrade cost
The repository is not archived, and the last push was on 2026-09-23. Recent releases are v3.4.0 on 2022-12-12, v3.4.1 on 2023-07-12 and v3.4.2 on 2024-12-20. The gap between the 3.4.2 release and the most recent commit activity is the number to keep in mind when you plan an upgrade: tagged releases arrive slowly, while the main branch keeps moving.
That combination has a practical consequence. If you install from a release binary you get a fixed, tested snapshot. If you build from source you get whatever is on main, and the README warns that non-Windows bugs may be introduced inadvertently. Pin to a release tag unless you are contributing.
The upgrade path from IronPython 2 has its own wiki article, and the README links it directly. Anyone migrating an existing 2.x codebase should read that page before touching code, because the Python 2 to 3 differences are compounded by the IronPython-specific ones.
Licensing is Apache-2.0, which permits commercial use and modification and includes an explicit patent grant. That is permissive and compatible with closed-source distribution, but the usual obligations apply: keep the licence and notice files, and state significant changes. This is not legal advice; have counsel review the NOTICE handling for your distribution form.
Reading the repository before you commit
The top-level layout tells you what to expect from the project's own documentation. There are separate What's New files for Python 3.0 through 3.6, which is how the team tracks implemented features per CPython version. A docs directory, an eng directory for build scripts and a tests directory sit alongside src. The solution file is IronPython.slnx and the build entry point is make.ps1.
Two files are worth opening before anything else. CurrentVersion.props tells you the version the tree currently reports, which may be ahead of the last tagged release. Directory.Build.props sets the shared build properties and is where the target frameworks in the README (4.6.2, .NET Standard 2.0, .NET 8.0, .NET 10.0) are reflected in the build configuration.
The README does not document a rollback procedure for an installed interpreter, and it does not describe a package manager story beyond ensurepip. If your deployment needs either, that gap is something you would have to solve yourself, and it is better to find that out from the wiki than after you have shipped.
Editorial conclusion
Adopt IronPython 3 when the Python code has to live inside a .NET process or the script has to reach .NET types directly, and when Python 3.4 level is enough. Do not adopt it as a general CPython replacement, and do not expect current Python 3 syntax or the full standard library. Before committing, check the Differences from CPython and Package compatibility wiki pages against the exact packages you need, and confirm that the target framework you ship on (4.6.2, .NET Standard 2.0, .NET 8.0 or .NET 10.0) is the one you actually build against.
Frequently asked questions
Is IronPython the same as Python?
No. IronPython is an open-source implementation of Python that is tightly integrated with .NET and built on the Dynamic Language Runtime, while CPython is the reference implementation. The README notes that compatibility with CPython is a main goal but that differences remain, documented on a Differences from CPython wiki page.
What is IronPython used for?
It is used to run Python code inside .NET and to let .NET languages call Python code. The README's example writes a Windows Forms MessageBox call in Python by importing clr and adding a reference to System.Windows.Forms, and a second example calls a Python function from C# through the hosting API.
How do I install IronPython?
Binaries are on the release page in .msi, .zip, .deb and .pkg formats, and the IronPython package is on NuGet. The README also gives a PowerShell one-liner that fetches Install-IronPython.ps1 and installs into a path you choose, with an optional ensurepip step.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/ironlanguages-ironpython3)