-->

Call Python from .NET

2019-01-23 15:52发布

问题:

I have some code written in Python which can not be transferred to a .NET language. I need to call one of these functions from my .NET WinForms application.

Now, I do it by starting the Python script as a separate process and pass parameters to it as command line arguments. It works, but I don't really like this solution. I'd like to improve it to a better one.

Is there any better way to call a function of a .py script from a .NET application? What is the best way to do it?

Note: IronPython is NOT an option for this Python script

回答1:

It works, but I don't really like this solution, I'd like to improve it to a better one.

No, AFAIK there isn't a better solution, especially if IronPython is a no-no for you. So you could still keep this as a temporary workaround while waiting for the script to be migrated to .NET or until you find that someone already wrote a library on .NET that provides you with similar functionality.



回答2:

This might be a lot more work than launching the Python process, but here's an alternate solution.

You can embed Python into another program. The API is for C and Interop from .NET will probably be a major pain. If you're into a bit of a safer way to handle the native Python API, you can look into Boost.Python, which, among its less advertised features, has support for embedding.

With these tools, you can write a C++ managed DLL that uses Boost.Python to load the Python interpreter and execute any Python script. Thus, you can execute any Python code directly in the hosting process, eliminating the use of an external process and any form of IPC.

Edit: AFAIK, all you have to add to your installation procedure is the deployment of the Python DLL and Boost.Python DLL.



回答3:

Besides the COM option, you could make your Python script instantiate a xmlrpc server - it is quite transparent and you never have to deal with "xml" on your own code.

Then, on .net side, you simply connect to your python app via xmlrpc - if there is no suitable way to do that in C#, just write a client function in IronPython.

The SimpleXMLRPCServer example on Python documentation is enough for that:

http://docs.python.org/library/simplexmlrpcserver.html



回答4:

I think you need to re-evaluate Carlos' answer. See the section Implementing COM Objects with Python in Mark Hammond's book Python Programming on Win32.

You should be able to create a COM object, then have .Net interact with it.

From the book the following will create a COM server with a single method.

# SimpleCOMServer.py - A sample COM server - almost as small as they come!
# 
# We expose a single method in a Python COM object.
class PythonUtilities:
    _public_methods_ = [ 'SplitString' ]
    _reg_progid_ = "PythonDemos.Utilities"
    # NEVER copy the following ID 
    # Use "print pythoncom.CreateGuid()" to make a new one.
    _reg_clsid_ = "{41E24E95-D45A-11D2-852C-204C4F4F5020}"

    def SplitString(self, val, item=None):
        import string
        if item != None: item = str(item)
        return string.split(str(val), item)

# Add code so that when this script is run by
# Python.exe, it self-registers.
if __name__=='__main__':
    print "Registering COM server..."
    import win32com.server.register
    win32com.server.register.UseCommandLine(PythonUtilities)

The book goes on to say ".. you can do this by executing the code as a normal Python script. The easiest way to do this is to open the source file in PythonWin and use the Run command from the File menu. "

I think you need the ActivePython distribution from Activestate to do it.

See this question Consuming Python COM Server from .NET



回答5:

Create a COM .dll from a .py script and use Interop in your .NET code. Have a look here: http://docs.python.org/faq/windows.html



回答6:

PythonNet should help with this one. It enables you to call python code from C#.

A cleaner way is to expose the python script via a Flask REST API and consume that from your .NET Application. Don't forget to put proper authentication in place.