shiena / Unity-PythonNet

https://zenn.dev/shiena/articles/unity-python
MIT License
20 stars 1 forks source link

Build it in windows and use it in other devices #3

Closed GeorgeGlyn closed 1 year ago

GeorgeGlyn commented 1 year ago

Hi, can you help me to take a build for windows. I took a build and it is working on my system but when I shared it to others it is showing some python modules missing also in the log it is showing the cs file path as the path where the app is build (my system) not the path of the build folder(my friend's system)?

Should i somehow make it to use the python from the build folder or change the path to use it dynamically?

shiena commented 1 year ago

By placing embeddable python in StreamingAssets and using the following initialization script, python can be executed without depending on the system. https://github.com/shiena/Unity-PythonNet/blob/main/Assets/Scripts/PythonLifeCycle.cs

Please refer to the article below for the steps to build the project. https://zenn.dev/shiena/articles/unity-python

GeorgeGlyn commented 1 year ago

Yes, I did the same but when I run it in other system it is showing the path of the CS

UnityPython.Proj.Start() (at D:/projects/my_project/Assets/Scripts/Proj/Proj.cs:37) file where it was build.

shiena commented 1 year ago

The priority of PATH was wrong, so please apply the following changes. https://github.com/shiena/Unity-PythonNet/commit/df3285241b0ea61c93dbdd023e154d7ef75ee365

GeorgeGlyn commented 1 year ago

Thanks, but I still have issues while importing python libraries like typing_extensions in the build copied to other systems. It's working for my system but not in other systems.

shiena commented 1 year ago

Are you able to run it directly from the command line? The command for this project is:

Assets\StreamingAssets\python-3.11.3-embed-amd64\python.exe Assets\StreamingAssets\myproject\plot_random.py

It seems that it will fail if there is a problem with the environment construction.

GeorgeGlyn commented 1 year ago

Yes it is working on my system and I received this error when I try to run the build in other system. The build in my system is working fine. D drive is where the project is and G drive is where the build is located.

`G:/unity-build/Build/Build-08-07-2023-1157/App_Data/StreamingAssets UnityEngine.StackTraceUtility:ExtractStackTrace () UnityEngine.DebugLogHandler:LogFormat (UnityEngine.LogType,UnityEngine.Object,string,object[]) UnityEngine.Logger:Log (UnityEngine.LogType,object) UnityEngine.Debug:LogError (object) PythonLifeCycle:Initialize (string) (at D:/Projects/App/Assets/Scripts/PythonLifeCycle.cs:28) PythonLifeCycle:PythonInitialize () (at D:/Projects/App/Assets/Scripts/PythonLifeCycle.cs:16)

(Filename: D:/Projects/App/Assets/Scripts/PythonLifeCycle.cs Line: 28)

G:/unity-build/Build/Build-08-07-2023-1157/App_Data/StreamingAssets UnityEngine.StackTraceUtility:ExtractStackTrace () UnityEngine.DebugLogHandler:LogFormat (UnityEngine.LogType,UnityEngine.Object,string,object[]) UnityEngine.Logger:Log (UnityEngine.LogType,object) UnityEngine.Debug:LogError (object) PythonLifeCycle:Initialize (string) (at D:/Projects/App/Assets/Scripts/PythonLifeCycle.cs:28) PythonInitializer:Start () (at D:/Projects/App/Assets/Scripts/PythonInitializer.cs:10)

(Filename: D:/Projects/App/Assets/Scripts/PythonLifeCycle.cs Line: 28)

PythonException: No module named 'typing_extensions' File "G:\unity-build\Build\Build-08-07-2023-1157\App_Data\StreamingAssets\python-3.10.6-embed-amd64\Lib\site-packages\torch\serialization.py", line 17, in from typing_extensions import TypeAlias # Python 3.10+ File "G:\unity-build\Build\Build-08-07-2023-1157\App_Data\StreamingAssets\python-3.10.6-embed-amd64\Lib\site-packages\torch__init.py", line 1122, in from .serialization import save, load File "G:\unity-build\Build\Build-08-07-2023-1157\App_Data\StreamingAssets\python-3.10.6-embed-amd64\Lib\site-packages\code\code.py", line 12, in import torch File "G:\unity-build\Build\Build-08-07-2023-1157\App_Data\StreamingAssets\python-3.10.6-embed-amd64\Lib\site-packages\code\init__.py", line 2, in from code.code import Code # noqa File "G:\unity-build\Build\Build-08-07-2023-1157\App_Data\StreamingAssets\myproject\translate.py", line 1, in from code import Code at Python.Runtime.PythonException.ThrowLastAsClrException () [0x00025] in <77462c434d854fc6846de1ac899c7833>:0 at Python.Runtime.NewReferenceExtensions.BorrowOrThrow (Python.Runtime.NewReference& reference) [0x0000f] in <77462c434d854fc6846de1ac899c7833>:0 at Python.Runtime.PyModule.Import (System.String name) [0x00015] in <77462c434d854fc6846de1ac899c7833>:0 at Python.Runtime.Py.Import (System.String name) [0x00000] in <77462c434d854fc6846de1ac899c7833>:0 at Translate.Start () [0x000db] in D:\Projects\App\Assets\Scripts\Translate.cs:29

(Filename: D:/Projects/App/Assets/Scripts/Translate.cs Line: 29)`

shiena commented 1 year ago

The syspath is displayed with the following command. Are there any differences between your two PCs?

Assets\StreamingAssets\python-3.11.3-embed-amd64\python.exe -c "import sys;print('\n'.join(sys.path))"
GeorgeGlyn commented 1 year ago

The syspath is displayed with the following command. Are there any differences between your two PCs?

Assets\StreamingAssets\python-3.11.3-embed-amd64\python.exe -c "import sys;print('\n'.join(sys.path))"

Thank you for the support. I managed to fix it based on your suggestion. This is my modified PythonLifeCycle.cs that works on all systems.

using Python.Runtime;
using System;
using UnityEngine;

public static class PythonLifeCycle
{
    private const string PythonFolder = "python-3.10.6-embed-amd64";
    private const string PythonDll = "python310.dll";
    private const string PythonZip = "python310.zip";
    private const string PythonProject = "myproject";

    [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)]
    private static void PythonInitialize()
    {
        Application.quitting += PythonShutdown;
        Initialize(PythonProject);
    }

    private static void PythonShutdown()
    {
        Application.quitting -= PythonShutdown;
        Shutdown();
    }

    public static void Initialize(string appendPythonPath = "")
    {
        var pythonHome = $"{Application.streamingAssetsPath}/{PythonFolder}";
        Debug.LogError(Application.streamingAssetsPath);
        var appendPath = string.IsNullOrWhiteSpace(appendPythonPath) ? string.Empty : $"{Application.streamingAssetsPath}/{appendPythonPath}";
        var path1 = $"{pythonHome}/{PythonZip}";
        var path2 = $"{pythonHome}/DLLs";
        var path3 = $"{pythonHome}/Lib";
        var path4 = $"{pythonHome}";
        var path5 = $"{pythonHome}/Lib/site-packages";
        var path6 = $"{pythonHome}/Lib/site-packages/win32";
        var path7 = $"{pythonHome}/Lib/site-packages/win32/lib";
        var path8 = $"{pythonHome}/Lib/site-packages/Pythonwin";

        var pythonPath = string.Join(";",
        $"{path1}",
        $"{path2}",
        $"{path3}",
        $"{path4}",
        $"{path5}",
        $"{path6}",
        $"{path7}",
        $"{path8}",
            $"{appendPath}",
            $"{pythonHome}/Lib/site-packages",
            $"{pythonHome}/{PythonZip}",
            $"{pythonHome}"
        );
        // Debug.LogError(pythonPath);

        var scripts = $"{pythonHome}/Scripts";

        var path = Environment.GetEnvironmentVariable("PATH")?.TrimEnd(';');
        // path = string.IsNullOrEmpty(path) ? $"{pythonHome};{scripts}" : $"{pythonHome};{scripts};{path}";

        path = $"{path1};{path2};{path3};{path4};{path5};{path6};{path7};{path8};";
        // path = $"{pythonHome};{scripts}";

        Environment.SetEnvironmentVariable("PATH", path, EnvironmentVariableTarget.Process);
        Environment.SetEnvironmentVariable("DYLD_LIBRARY_PATH", $"{pythonHome}/Lib", EnvironmentVariableTarget.Process);
        Environment.SetEnvironmentVariable("PYTHONNET_PYDLL", $"{pythonHome}/{PythonDll}", EnvironmentVariableTarget.Process);
        Environment.SetEnvironmentVariable("PYTHONPATH", $"{pythonHome}/Lib/site-packages", EnvironmentVariableTarget.Process);
#if UNITY_EDITOR
            Environment.SetEnvironmentVariable("PYTHONDONTWRITEBYTECODE", "1", EnvironmentVariableTarget.Process);
#endif

        PythonEngine.PythonHome = pythonHome;
        PythonEngine.PythonPath = pythonPath;

        PythonEngine.Initialize();
    }

    public static void Shutdown()
    {
        PythonEngine.Shutdown();
    }
}