Wiki

Clone wiki

PyDotnet / Home

1407024469-pydotnet-banner.png

tdlr;

Please, read this page fully

  • Yes, your .NET assemblies will work with PyDotnet (but only as long as they aren't troublesome)

  • PyDotnet runs .NET CLR within Python process boundaries (via C++/CLI extensions)

  • Make sure you understand how to load your assemblies: add_assemblies() and load_assembly() (see Using PyDotnet with .NET assemblies below)

    • You MUST call load_assembly(TheAssembly) and then import TheNamespace in order to use ANY class defined in that TheNamespace in that TheAssembly
  • Make sure you understand the difference between import dotnet and import dotnet.seamless

  • NEVER EVER use from dotnet import *

  • Make sure you install MSVCRT in correct version (see Installation below)

  • IMPORTANT Python 3.6 Note: Please go to C:\Python36\Lib\site-packages\dotnet folder and rename:

    • boost_python3-vc*-mt-1_64.dllboost_python3-vc150-mt-1_64.dll
    • boost_python-vc*-mt-1_64.dllboost_python-vc150-mt-1_64.dll
  • Please, also see THIS ISSUE

  • Latest version only available for Python 2.7 and 3.6 64 bit (due to changes on PyPi I wasn't able to upload other releases)

  • Make sure you read MSDN documentation if you trying to use Microsoft .NET classes

  • Windows ONLY - Mac / Linux NOT SUPPORTED Please, if you convince Microsoft to release C++/CLI compiler for Mac / Linux then we can talk...

IMPORTANT NOTE

Issues reported without reading fully provided wiki pages will be closed immediately.

Make sure you watch our HTML Presentation

To watch download html file and open it in your browser. Use keyboard arrows to navigate and ESC to see all slides at once. For more info visit (RevealJS) [http://lab.hakim.se/reveal-js/#/].

You can also see my:

About Me

sligo-1.jpg

My-self I am programmer with 19 years of experience in this profession. I have number of hobbies, but my most favourite is modelling.

It Just Works!

Once you install it using command line:

pip install dotnet

Then just use it immediately, and it simply works!

import dotnet.seamless
seq = List[Int32]([1,2,3,4,5])
seq.AddRange([6,7,8,9])

index = seq.FindIndex(lambda x: x > 3)

assert index == 3
dct = Dictionary[String, Int32]({'x':1, 'y':2})

x, has_x = dct.TryGetValue('x')
y, has_y = dct.TryGetValue('y')
z, has_z = dct.TryGetValue('z')

assert has_x and x == 1
assert has_y and y == 2
assert not has_z

If it doesn't?

The above example must just work without any other action on your side. If it doesn't, then it is very likely that you are missing some Windows DLL(s) (please, see information below).

Already PyDotnet user? Check your version!

Most recent: v1.3.1 (June 29th, 2017)

See Release Notes for more information.

Check PyPI Database.

Linux NOT SUPPORTED

The required compiler feature C++/CLI is a requirement that neither Mono nor GCC support.

Code Examples?

I don't have any specific examples besides what is provided here on wiki pages.

Note that I presume you understand how .NET works, and how to write Python code.

Essentially you import your .NET module, and use its classes same as you would do that in C#, but using Python syntax. If you have C# code that works, you can simply remove all types from variables and functions and that would probably work in Python with dotnet module.

You can also browse through sources in the dotnet the folder to see how things are done. For instance if you look into asmresolve.py you will see how Python modules (e.g. os, glob) are seamlessly mixed with .NET modules (e.g. System, System.Reflection). You will see python code using .NET methods, enums, or reflection. You can also see Python code set as .NET callback (e.g. domain.add_AssemblyResolve(self.__load), where domain is System.AppDomain, AssemblyResolve is an event, and self.__load is regular Python method).

Works With Azure?

I used it with various .NET modules including some of the Microsoft Azure ones, e.g. Microsoft.ServiceBus or Microsoft.WindowsAzure.Storage. Using those two I could easily interact with Azure Service Bus and Azure Cloud Table.

Here is Pythonised example from MSDN, which should work:

    import dotnet

    dotnet.add_assemblies(r'the/folder/where/you/have/Microsoft.ServiceBus.dll')
    dotnet.load_assembly('Microsoft.ServiceBus')

    import System
    from Microsoft.ServiceBus.Messaging import *

    connectionString = "<your service bus connection string>"
    topicName = "<your topic name>"

    client = TopicClient.CreateFromConnectionString(connectionString, topicName)
    message = BrokeredMessage[System.Object]("This is a test message!")

    print("Message body: {0}".format(message.GetBody[String]()))
    print("Message id: {0}".format(message.MessageId))

    client.Send(message);

    print("Message successfully sent!")

Can it glue C# and Java?

I haven't created any PyJava project, but there already exists one interesting option:

Imagine you can use your Python to create instances of C# classes and at the same time instances of Java classes.

What is more interesting you can potentially make these two talk to each other via Python!

If you try that Contact me and tell me how that worked :D

Help us

We would like to know how you find this project. Did you have any issues installing PyDotnet? Did it work straight away? Is it clear how to get started? What was your original reason to check this project?

Please, you can Contact me. I greatly appreciate your feedback.

Feel welcome to contribute. Try building module on your machine. Does it just build? Did you have any issues? At present there is no unit tests. Ideas, bugs, feature requests?

About

This is a module for Python that provides interoperability with the Microsoft .NET Framework.

Allows you to use CLR from within regular CPython. Both Python 2.7 and Python 3+ are supported, 32 and 64 bit are available.

Performance wise it shouldn't be slower than Python it-self. I guess that since .NET Reflection mechanism is same slow as Python's dynamic attribute resolution. However Python code pre-compiles to bytecode, and may run faster then, while .NET method calls remain calls via Reflection, so that is slower.

Usage

Define classes in C#, compile them into assembly, launch Python, import dotnet.seamless, and load your .NET assembly, and now you can use your C# classes as if they were part of Python.

See also

You may find information you were looking for in one of the following articles:

What is the difference between PyDotnet and IronPython?

The IronPython is Python language implementation on top of .NET framework, and it may not allow you to use your favorite native Python modules.

While PyDotnet is just another module for native Python. This way you can use it together with NumPy, Pandas, Spyder, etc.

Besides that PyDotnet is built to match Python style and thus it's highly flexible.

Its core has been written in mixed-mode C++ with use of Boost.Python, and then on top of that there is Python icing layer, where things like assembly resolution, generic method resolution, extension method resolution, private member access have been implemented. The core layer has been designed to provide all that is needed to let everything else be implemented purely in Python.

Status

This project has been approved for release to public. Please, see License.

Build system works with Win32 and Win64 distributions of CPython and Anaconda, and there is no build for Linux. I did some research and I couldn't find C++/CLI implementation for Linux, and PyDotnet requires C++/CLI in order to build.

You can also try building project your-self from within Visual Studio. Please follow steps in README.txt.

Installation

Use PIP to install.

pip install dotnet

BUILDS

  • dotnet version 1.3.1 - 64-bit Python 2.7 and 3.6 - you need MSVC 2017 CRT
  • dotnet version 1.2.1 - 32-bit and 64-bit Python 2.7 and 3.5 - you need MSVC 2015 CRT

The latest 1.3.1 version is built for 64-bit Python 2.7 and 3.6 using Visual Studio 2017 and Boost 1.64.

In order to create your own build, please follow README instructions.

See Release Notes for more information.

Example

Once you install PyDotnet you can copy & paste following example straight into Python interactive console and it will just work.

# Import Py.NET module
import dotnet.seamless

# Source of the Example C# class
src = '''
namespace Foo {
    public class Example {
        public Example(int x, string s) {
            m_x = x;
            m_s = s;
        }

        public void Set(int x, string s) {
            m_x = x;
            m_s = s;
        }

        public int X { get { return m_x; } }
        public string S { get { return m_s; } }

        private int m_x;
        private string m_s;
    }
}
'''

# Build module
dotnet.build_assembly(src, 'Foo.dll', [], '')

# Import module
import Foo

# Create instance
example = Foo.Example(1, 's')

# Call method
example.Set(5, 'B')

print('{0.X} {0.S}'.format(example))

In this particular example C# code has been injected into Python code as a string, then built into .NET assembly, and later C# class is used in Python.

The build_assembly takes a string containing C# code and compiles it into .NET assembly, and then it also loads that assembly into current Python process.

Using PyDotnet with .NET assemblies

You can use add_assemblies(path) and load_assembly(name) to load any .NET assembly you already have including the ones you built with Visual Studio or MSBuild. See Loading NET Assemblies for details.

The only limitation is platform compatibility, i.e. if you are running 64-bit Python, then you must either load 64-bit or MSIL .NET assemblies. Otherwise than that the Py.NET module should work with any .NET assemblies. Note that MSIL (a.k.a. Any CPU) assemblies will load regardless of Python bitness. That means mostly all of your .NET assemblies will just work.

Should you have any errors while using PyDotnet please copy & paste the error, and Contact me. Thank you.

Assembly Search Path & Dependencies

You load assembly with load_assembly(name), and that also loads all dependent assemblies. And for this to work properly you must set assembly search path.

Initially search path is completely empty, and does not include current directory nor GAC path.

The search path for assemblies is built using add_assemblies(path), which you may call multiple times and that will add multiple paths. The search order is first added path is checked first.

Note Sometimes types defined in assembly you just loaded are not accessible. Not sure the reason, but you may try to add extra load_assembly() call to load some random assembly, or maybe even better to try loading an assembly that depends on the assembly, where type you do not have access to is defined. Not sure why, but if you can find out and help me I'd be grateful.

Thank you

Sligo-2.jpg

We thank you for your interest:)

Updated