Using the Python API
The Python Script Editor makes it easy to test Python scripts and to create a menu item to allow users to easily access the script.
In addition you can directly call Python from your C# scripts. Python Scripting offers a high-level API and a low-level API.
High-level API: PythonRunner.RunString
The following C# code will create a menu item that prints "hello world" in the Unity console:
using UnityEditor.Scripting.Python;
using UnityEditor;
public class HelloWorld
{
    [MenuItem("Python/Hello World")]
    static void PrintHelloWorldFromPython()
    {
        PythonRunner.RunString(@"
                import UnityEngine;
                UnityEngine.Debug.Log('hello world')
                ");
    }
}
You can use any assembly that is available in C# by simply importing it with the
Python import statement -- in the example, we show importing UnityEngine.
PythonRunner.RunFile
Instead of inlining your Python code inside of a C# script, you can execute a
whole Python script using the PythonRunner.RunFile method. For example, this
Python script loops over all the GameObjects in a scene and makes sure all the
names end up with an underscore:
import UnityEngine
all_objects = UnityEngine.Object.FindObjectsOfType(UnityEngine.GameObject)
for go in all_objects:
    if go.name[-1] != '_':
        go.name = go.name + '_'
Put this file in Assets/ensure_naming.py. Script files can be located
anywhere on your file system, they don't need to be in the project.
You can run this Python script from C# as follows:
using UnityEditor.Scripting.Python;
using UnityEditor;
using UnityEngine;
public class EnsureNaming
{
    [MenuItem("Python/Ensure Naming")]
    static void RunEnsureNaming()
    {
        PythonRunner.RunFile($"{Application.dataPath}/ensure_naming.py");
    }
}
Low-level API
You can directly use Python for .NET, which wraps the CPython API. Using the C#
dynamic type, you can write C# that looks like Python. Refer to the Python
for .NET documentation.
There are some caveats:
- Make sure Python is properly initialized by calling 
PythonRunner.EnsureInitialized(). - Always grab the CPython Global Interpreter Lock (GIL).
 
Sample code:
using Python.Runtime;
using UnityEditor.Scripting.Python;
public class MyPythonScript
{
    [MenuItem("MyPythonScript/Run")]
    public static void Run()
    {
        PythonRunner.EnsureInitialized();
        using (Py.GIL()) {
            try {
                dynamic sys = Py.Import("sys");
                UnityEngine.Debug.Log($"python version: {sys.version}");
            } catch(PythonException e) {
                UnityEngine.Debug.LogException(e);
            }
        }
    }
}
You'll need to add an assembly reference in order for the compiler to know
where to find the low-level API in Python.Runtime. In the project view,
right-click and create a new assembly reference:

Then add a reference to com.unity.scripting.python.editor:
