Incorporate processing made with python into C # [python net preparation + confirmation edition January 2021 latest]

Overview

You may want to move the process created by python (mainly deep learning system such as tensorflow, pytorch) from GUI and display the result. It may be possible to use PyQt, but since there are many people around me who can handle C #, I thought it would be nice to be able to incorporate it, and I found out. The following ancestors have summarized how to use it, so I would like to write an article on the procedure up to making an application using the model actually made with tensorflow based on it. ** This article is about preparation and operation check. ** ** (** As of January 2021, the source code of pythonnet itself has been updated, so the latest procedure will be posted **) I'm a C # beginner, so please understand that there may be some mistakes ...

Reference (1): Call python from .NET (C #) Reference (2): I tried to execute Python code from .Net using Pythonnet (Hallo World edition)

0. Premise

** Development environment ** visualstudio2019 community Version 16.7.7 NuGet Package Manager 5.7.0 Anaconda Navigator 1.9.12

** C # environment ** .NET Framework 4.7.2

** python environment ** Python 3.7.6 tensorflow 2.3.0 numpy 1.18.5

** Prerequisite knowledge ** ・ People who can build environment with pip etc. with python and can code ・ People who understand C # a little

1. Introduction of pythonnet

Introduced with Nuget

If you use python3.7, you can easily install it using Nuget (as of 2021/01/10) 画面④.png ⇒ 2. Please skip until you call and use

Build and install by yourself

I referred to the following article. If you have an old source code of pythonnet, please refer to the following article.

Reference: Call python from .NET (C #) Reference: I tried running Python code from .Net using Pythonnet (Hallo World)

** This section describes how to build with the latest source code as of January 10, 2021. ** **

  1. Clone Latest Code from pythonnet's github repository and open pythonnet.sln

  2. Open the project properties of project Python.Runtime and manually enter the compile symbol. If you want to use python3.8, enter PYTHON38; WINDOWS. For 3.7, change PYTHON38 to 37. 画面①.png By the way, if you look at the contents of runtime.cs, you can see how to set the compile symbol. ** If you do not enter WINDOWS, the content of the dll will be python38, and when you actually use it, you will go looking for python3.8, so you will not be able to load the dll properly. ** ** 画面②.png

  3. Right-click in Python.Runtime in Solution Explorer and select Build

If the build passes successfully, the root folder src\runtime\bin\Debug\netstandard2.0 To Python.Runtime.dll I think that has been generated.

2. Call pythonnet from C # and try using it

Reference: Call python from .NET (C #) I'm just imitating how to write the code of the ancestor, but I will try to make an application that puts a label on the form, displays the version of numpy, and makes a simple calculation with numpy.

1. Make a form solution

画面③.png 画面④.png

2. Platform change

画面⑤.png 画面⑥.png 画面⑦.png

Make sure the platform is x64. image.png

3. Add reference

Browse to the DLL file you just created 画面⑧.png画面⑨.png image.png

Make sure Python.Runtime is added. 画面⑩.png

4. Sample code creation

Please make a form like this. image.png

Reference: Call python from .NET (C #) All you have to do is refer to the code of the predecessor.

Form.cs


using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Drawing.Imaging;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.IO;
using System.Runtime.InteropServices;

using Python.Runtime;

namespace pythonnet_numpy_version
{
    public partial class Form1 : Form
    {
        /// <summary>
        ///Variables for sharing and using the python library
        /// </summary>
        public dynamic np;
        public Form1()
        {
            InitializeComponent();
        }

        /// <summary>
        ///Add the specified directory to the process's environment variable PATH(Pass through)。
        /// </summary>
        /// <param name="paths">The directory to add to your PATH.</param>
        public static void AddEnvPath(params string[] paths)
        {
            var envPaths = Environment.GetEnvironmentVariable("PATH").Split(Path.PathSeparator).ToList();
            foreach (var path in paths)
            {
                if (path.Length > 0 && !envPaths.Contains(path))
                {
                    envPaths.Insert(0, path);
                }
            }
            Environment.SetEnvironmentVariable("PATH", string.Join(Path.PathSeparator.ToString(), envPaths), EnvironmentVariableTarget.Process);
        }
        //Process when the form is called
        private void Form1_Load(object sender, EventArgs e)
        {
            // *-------------------------------------------------------*
            // *python environment settings
            // *-------------------------------------------------------*

            //Pass the path to the python environment
            // TODO:Correct the path according to the environment
            var PYTHON_HOME = Environment.ExpandEnvironmentVariables(@@"%userprofile%\Anaconda3\envs\tensorflow-2-3-0");
            //Allows pythonnet to find python body DLLs and dependent DLLs
            AddEnvPath(
              PYTHON_HOME,
              Path.Combine(PYTHON_HOME, @"Library\bin")
            );

            //PYTHON in python environment_HOME(Location of standard python library)The set
            PythonEngine.PythonHome = PYTHON_HOME;

            //Process python = Display numpy definition and version on label
            using (Py.GIL())
            {
                //numpy import
                np = Py.Import("numpy");
                //Store numpy version in variable
                dynamic np_version = np.__version__;
                //Make it a string type, concatenate it with a character string, and display it on the label
                labelNumpyVersion.Text = "numpy version:" + np_version.ToString();
            }
        }
        //Click the button to do a simple calculation using the numpy method and display it on the label
        private void buttonCalc_Click(object sender, EventArgs e)
        {
            //Do a simple calculation and store it in a variable
            dynamic result = np.cos(np.pi / 3);
            //Even if you do not ToString, if you attach it to a character string, it will change the type without permission
            labelResult.Text = "np.cos(np.pi / 3)=" + result;
        }
    }
}

Basically, just write according to the article you are referring to, but one point is that in the case of a form application, you want to use numpy with various controls, so you need to define the member variables to be stored when importing. The summary is as follows. (Depending on how you use it, there may be an appropriate setting for the access modifier ... I decided to make it public for the time being)

Definition of member variables

hogehoge.cs


    public partial class Form1 : Form
    {
        /// <summary>
        ///Variables for sharing and using the python library
        /// </summary>
        public dynamic np;

Definition of numpy

hogehoge.cs


            //Process python = Display numpy definition and version on label
            using (Py.GIL())
            {
                //numpy import
                np = Py.Import("numpy");

Use of numpy

hogehoge.cs


            //Do a simple calculation and store it in a variable
            dynamic result = np.cos(np.pi / 3);

3. At the end

I started programming from python, and after studying C #, it took me about half a day to build pythonnet in a few months, which seemed to break my heart, but I was relieved to be able to shape it.

Next, I will write an article to make an application that reads an image on the C # side using tensorflow and opencv and displays the result inferred by the segmentation model with python in the picturebox of C #.

that's all. If you have any questions or concerns, please leave a comment.

Recommended Posts

Incorporate processing made with python into C # [python net preparation + confirmation edition January 2021 latest]
I made a net news notification app with Python
Scraping with Python (preparation)
Container-like # 1 made with C
Container-like # 2 made with C
Image processing with Python
Embed a Python interpreter into a C ++ app with pybind11 + cmake