- Notifications
You must be signed in to change notification settings - Fork0
christabella/pythonnet.github.io
Folders and files
Name | Name | Last commit message | Last commit date | |
---|---|---|---|---|
Repository files navigation
Python.NET (pythonnet
) is a package that gives Python programmersnearly seamless integration with the .NET 4.0+ Common Language Runtime(CLR) on Windows and Mono runtime on Linux and OSX. Python.NETprovides a powerful application scripting tool for .NET developers.Using this package you can script .NET applications or build entireapplications in Python, using .NET services and components written inany language that targets the CLR (C#, VB.NET, F#, C++/CLI).
Note that this package doesnot implement Python as a first-class CLRlanguage - it does not produce managed code (IL) from Python code. Rather,it is an integration of the CPython engine with the .NET or Mono runtime.This approach allows you to use CLR services and continue to use existingPython code and C-API extensions while maintaining native executionspeeds for Python code. If you are interested in a pure managed-codeimplementation of the Python language, you should check out theIronPython project, which is in active development.
Python.NET is currently compatible and tested with Python releases2.7 and 3.5-3.8.Current releases are available at thePython.NET website.To subscribe to thePython.NET mailing list or read theonline archives of the list, see themailing list informationpage. Use thePython.NET issue tracker to report issues.
- This page provides a detailed overview of Python.NET,as well as some basic usage examples. Many other examples can befound in the demos and unit tests for the package.
- Checkout thePythonNet code from github.
- Download releases for various versions of Python and CLR.
Python.NET is available as a source release onGitHub and as abinary wheel distribution for all supported versions of Python and thecommon language runtime from thePython Package Index.
The source release is a self-contained "private" assembly. Just unzip thepackage wherever you want it, cd to that directory, build the solutionpython setup.py build_ext --inplace
. Once you start up Python orIPython interpreter in this directory or append this directory tosys.path
, then afterimport clr
statement .NET assemblies canbe used.You can also runnPython.exe
(mono nPython.exe
on*nix
) to checkhow python can be embedded in console .NET application. Note that thesource release does not include a copy of the CPython runtime, so you willneed to have installed Python on your machine before using the source release.
Running on Linux/Mono: Unit testing shows that PythonNet will rununderMono, though the Mono runtime is less supported so there stillmay be problems.
A key goal for this project has been that Python.NET should"work just the way you'd expect in Python", except for cases that are.NET specific (in which case the goal is to work "just the wayyou'd expect in C#"). In addition, with the IronPython project havingestablished a community, it is my goal that code written for IronPythonrun without modification under Python.NET.
If you already know Python, you can probably finish this readme and thenrefer to .NET docs to figure out anything you need to do. Conversely ifyou are familiar with C# or another .NET language, you probably just needto pick up one of the many good Python books or read the Python tutorialonline to get started.
A good way to start is to interactively explore .NET usage in pythoninterpreter by following along with the examples in this document. If youget stuck, there are also a number of demos and unit tests located in thesource directory of the distribution that can be helpful as examples.
Python.NET allows CLR namespaces to be treated essentially asPython packages.
fromSystemimportStringfromSystem.Collectionsimport*
Types from any loaded assembly may be imported and used in this manner.To load an assembly, use theAddReference
function in theclr
module:
importclrclr.AddReference("System.Windows.Forms")fromSystem.Windows.FormsimportForm
Note Earlier releases of Python.NET relied on "implicit loading"to support automatic loading of assemblies whose names corresponded to animported namespace. Implicit loading still works for backward compatibility,but will be removed in a future release so it is recommended to usetheclr.AddReference
method.
Python.NET uses the PYTHONPATH (sys.path) to look for assembliesto load, in addition to the usual application base and the GAC. To ensurethat you can implicitly import an assembly, put the directory containingthe assembly insys.path
.
Python.NET allows you to use any non-private classes, structs,interfaces, enums or delegates from Python. To create an instance of amanaged class, you use the standard instantiation syntax, passing a setof arguments that match one of its public constructors:
fromSystem.DrawingimportPointp=Point(5,5)
In most cases, Python.NET can determine the correct constructor tocall automatically based on the arguments. In some cases, it may be necessaryto call a particular overloaded constructor, which is supported by a special__overloads__
attribute, which will soon be deprecated in favor ofiPy compatible "Overloads", on a class:
fromSystemimportString,Char,Int32s=String.Overloads[Char,Int32]('A',10)s=String.__overloads__[Char,Int32]('A',10)
Pythonnet also supports generic types. A generic type must be bound tocreate a concrete type before it can be instantiated. Generic types supportthe subscript syntax to create bound types:
fromSystem.Collections.GenericimportDictionaryfromSystemimport*dict1=Dictionary[String,String]()dict2=Dictionary[String,Int32]()dict3=Dictionary[String,Type]()
When you pass a list of types using the subscript syntax, you can alsopass a subset of Python types that directly correspond to .NET types:
dict1=Dictionary[str,str]()dict2=Dictionary[str,int]()dict3=Dictionary[str,Decimal]()
This shorthand also works when explicitly selecting generic methods orspecific versions of overloaded methods and constructors (explained later).
You can also subclass managed classes in Python, though members of thePython subclass are not visible to .NET code. See thehelloform.py
filein the/demo
directory of the distribution for a simple Windows Formsexample that demonstrates subclassing a managed class.
You can get and set fields and properties of CLR objects just as if theywere regular attributes:
fromSystemimportEnvironmentname=Environment.MachineNameEnvironment.ExitCode=1
If a managed object implements one or more indexers, you can call theindexer using standard Python indexing syntax:
fromSystem.CollectionsimportHashtabletable=Hashtable()table["key 1"]="value 1"
Overloaded indexers are supported, using the same notation one woulduse in C#:
items[0,2]items[0,2,3]
Methods of CLR objects behave generally like normal Python methods.Static methods may be called either through the class or through aninstance of the class. All public and protected methods of CLR objectsare accessible to Python:
fromSystemimportEnvironmentdrives=Environment.GetLogicalDrives()
It is also possible to call managed methodsunbound
(passing the instance as the first argument) just as with Python methods.This is most often used to explicitly call methods of a base class.
Note There is one caveat related to calling unbound methods: it ispossible for a managed class to declare a static method and an instancemethod with the same name. Since it is not possible for the runtime to knowthe intent when such a method is called unbound, the static method willalways be called.
The docstring of CLR a method (doc) can be used to view the signatureof the method, including overloads if the CLR method is overloaded.You can also use the Pythonhelp
method to inspect a managed class:
fromSystemimportEnvironmentprint(Environment.GetFolderPath.__doc__)help(Environment)
While Python.NET will generally be able to figure out the rightversion of an overloaded method to call automatically, there are caseswhere it is desirable to select a particular method overload explicitly.
Methods of CLR objects have an__overloads__
, which will soon bedeprecated in favor of iPy compatible Overloads, attribute that can beused for this purpose:
fromSystemimportConsoleConsole.WriteLine.Overloads[bool](true)Console.WriteLine.Overloads[str]("true")Console.WriteLine.__overloads__[int](42)
Similarly, generic methods may be bound at runtime using the subscriptsyntax directly on the method:
someobject.SomeGenericMethod[int](10)someobject.SomeGenericMethod[str]("10")
Delegates defined in managed code can be implemented in Python.A delegate type can be instantiated and passed a callable Python objectto get a delegate instance. The resulting delegate instance is a truemanaged delegate that will invoke the given Python callable when itis called:
defmy_handler(source,args):print('my_handler called!')# instantiate a delegated=AssemblyLoadEventHandler(my_handler)# use it as an event handlerAppDomain.CurrentDomain.AssemblyLoad+=d
Multicast delegates can be implemented by adding more callable objects toa delegate instance:
d+=self.method1d+=self.method2d()
Events are treated as first-class objects in Python, and behave in manyways like methods. Python callbacks can be registered with event attributes,and an event can be called to fire the event.
Note that events support a convenience spelling similar to that used in C#.You do not need to pass an explicitly instantiated delegate instance to anevent (though you can if you want). Events support the+=
and-=
operators in a way very similar to the C# idiom:
defhandler(source,args):print('my_handler called!')# register event handlerobject.SomeEvent+=handler# unregister event handlerobject.SomeEvent-=handler# fire the eventresult=object.SomeEvent(...)
You can raise and catch managed exceptions just the same as you wouldpure-Python exceptions:
fromSystemimportNullReferenceExceptiontry:raiseNullReferenceException("aiieee!")exceptNullReferenceExceptionase:print(e.Message)print(e.Source)
The typeSystem.Array
supports the subscript syntax in order tomake it easy to create managed arrays from Python:
fromSystemimportArraymyarray=Array[int](range(10))
Managed arrays support the standard Python sequence protocols:
items=SomeObject.GetArray()# Get first itemv=items[0]items[0]=v# Get last itemv=items[-1]items[-1]=v# Get lengthl=len(items)# Containment testtest=vinitems
Multidimensional arrays support indexing using the same notation onewould use in C#:
items[0,2]items[0,2,3]
Managed arrays and managed objects that implement the IEnumerableinterface can be iterated over using the standard iterationPython idioms:
domain=System.AppDomain.CurrentDomainforitemindomain.GetAssemblies():name=item.GetName()
Using Microsoft-provided tools such asaximp.exe
andtlbimp.exe
,it is possible to generate managed wrappers for COM libraries. Aftergenerating such a wrapper, you can use the libraries from Python justlike any other managed code.
Note: currently you need to put the generated wrappers in the GAC, inthe PythonNet assembly directory or on the PYTHONPATH in order to load them.
Type conversion under Python.NET is fairly straightforward - mostelemental Python types (string, int, long, etc.) convert automatically tocompatible managed equivalents (String, Int32, etc.) and vice-versa.Note that all strings returned from the CLR are returned as unicode.
Types that do not have a logical equivalent in Python are exposed asinstances of managed classes or structs (System.Decimal is an example).
The .NET architecture makes a distinction betweenvalue types
andreference types
. Reference types are allocated on the heap, and valuetypes are allocated either on the stack or in-line within an object.
A process calledboxing
is used in .NET to allow code to treat a valuetype as if it were a reference type. Boxing causes a separate copy of thevalue type object to be created on the heap, which then has referencetype semantics.
Understanding boxing and the distinction between value types and referencetypes can be important when using Python.NET because the Pythonlanguage has no value type semantics or syntax - in Python"everything is a reference".
Here is a simple example that demonstrates an issue. If you are anexperienced C# programmer, you might write the following code:
items=System.Array.CreateInstance(Point,3)foriinrange(3):items[i]=Point(0,0)items[0].X=1# won't work!!
While the spelling ofitems[0].X = 1
is the same in C# and Python,there is an important and subtle semantic difference.In C# (and other compiled-to-IL languages), the compiler knows thatPoint is a value type and can do the Right Thing here, changing thevalue in place.
In Python however, "everything's a reference", and there is really nospelling or semantic to allow it to do the right thing dynamically.The specific reason thatitems[0]
itself doesn't change is that whenyou sayitems[0]
, that getitem operation creates a Python object thatholds a reference to the object atitems[0]
via a GCHandle.That causes a ValueType (like Point) to be boxed, so the followingsetattr (.X = 1
)changes the state of the boxed value,not the original unboxed value.
The rule in Python is essentially:
the result of any attribute or item access is a boxed value
and that can be important in how you approach your code.
Because there are no value type semantics or syntax in Python,you may need to modify your approach. To revisit the previous example,we can ensure that the changes we want to make to an array itemaren't "lost" by resetting an array member after making changes to it:
items=System.Array.CreateInstance(Point,3)foriinrange(3):items[i]=Point(0,0)# This _will_ work. We get 'item' as a boxed copy of the Point# object actually stored in the array. After making our changes# we re-set the array item to update the bits in the array.item=items[0]item.X=1items[0]=item
This is not unlike some of the cases you can find in C# where you have toknow about boxing behavior to avoid similar kinds oflost update
problems(generally because an implicit boxing happened that was not takeninto account in the code).
This is the same thing, just the manifestation is a little differentin Python. See the .NET documentation for more details on boxing and thedifferences between value types and reference types.
Note: because Python code running under Python.NET is inherentlyunverifiable, it runs totally under the radar of the security infrastructureof the CLR so you should restrict use of the Python assembly to trusted code.
The Python runtime assembly defines a number of public classes thatprovide a subset of the functionality provided by the Python C-API.
These classes include PyObject, PyList, PyDict, PyTuple, etc.You can review the nPython.exe source code in in "Console.csproj" projectfor example of embedding CPython in console .NET app. Please refer tothis README GitHub page for new simplified embedding API:
At a very high level, to embed Python in your application you will need to:
- Reference Python.Runtime.dll in your build environment
- Call PythonEngine.Initialize() to initialize Python
- Call PythonEngine.ImportModule(name) to import a module
The module you import can either start working with your managed appenvironment at the time its imported, or you can explicitly lookup andcall objects in a module you import.
For general-purpose information on embedding Python in applications,usewww.python.org or Google to find (C) examples. BecausePython.NET is so closely integrated with the managed environment,you will generally be better off importing a module and deferring toPython code as early as possible rather than writing a lot of managedembedding code.
Important Note for embedders: Python is not free-threaded anduses a global interpreter lock to allow multi-threaded applicationsto interact safely with the Python interpreter.Much more information about this is available in the Python C-APIdocumentation on thewww.python.org Website.
When embedding Python in a managed application, you have to manage theGIL in just the same way you would when embedding Python ina C or C++ application.
Before interacting with any of the objects or APIs provided by thePython.Runtime namespace, calling code must have acquired the Pythonglobal interpreter lock by calling thePythonEngine.AcquireLock
method.The only exception to this rule is thePythonEngine.Initialize
method,which may be called at startup without having acquired the GIL.
When finished using Python APIs, managed code must call a correspondingPythonEngine.ReleaseLock
to release the GIL and allow other threadsto use Python.
Ausing
statement may be used to acquire and release the GIL:
using(Py.GIL()){PythonEngine.Exec("doStuff()");}
The AcquireLock and ReleaseLock methods are thin wrappers over theunmanagedPyGILState_Ensure
andPyGILState_Release
functions fromthe Python API, and the documentation for those APIs applies tothe managed versions.
This section demonstrates how to pass a C# object to the Python runtime.The example uses the followingPerson
class:
publicclassPerson{publicPerson(stringfirstName,stringlastName){FirstName=firstName;LastName=lastName;}publicstringFirstName{get;set;}publicstringLastName{get;set;}}
In order to pass a C# object to the Python runtime, it must be converted to aPyObject
. This is done using theToPython()
extension method. ThePyObject
may then be set as a variable in aPyScope
. Code executed from the scopewill have access to the variable:
// create a person objectPersonperson=newPerson("John","Smith");// acquire the GIL before using the Python interpreterusing(Py.GIL()){// create a Python scopeusing(PyScopescope=Py.CreateScope()){// convert the Person object to a PyObjectPyObjectpyPerson=person.ToPython();// create a Python variable "person"scope.Set("person",pyPerson);// the person object may now be used in Pythonstringcode="fullName = person.FirstName + ' ' + person.LastName";scope.Exec(code);}}
Python.NET is released under the open source MIT License.A copy of the license is included in the distribution,or you can find a copy of thelicense online.
Some distributions of this package include a copy of the C Python dlls andstandard library, which are covered by thePython license.
This project is supported by the.NET Foundation.
About
homepage
Resources
License
Uh oh!
There was an error while loading.Please reload this page.