Проблема Python.net при работе с модулями в Ubuntu 22.04, но работает в Windows 11

У меня есть очень простое приложение C#, использующее Python.net 3.0.3 в net8.0, которое пытается вызвать модуль Python в каталоге bin/Debug/net8.0, который возвращает произведение двух чисел. В Windows это работает, в Ubuntu я получаю Python.Runtime.PythonException с сообщением No module named 'script'. Файлы на обеих машинах одинаковые.

Код:

namespace PythonLoader
{
    using System;
    using System.Runtime.InteropServices;
    using GetSomeInput;
    using Python.Runtime;

    public class Program
    {
        public static void Main(string[] args)
        {
            try
            {
                string script = Inputty.GetString("Module name: ", "script", false);

                if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
                {
                    Runtime.PythonDLL = @"C:\Python312\python312.dll";
                }
                else
                {
                    // see https://stackoverflow.com/questions/20582270/distribution-independent-libpython-path
                    Runtime.PythonDLL = @"/usr/lib/x86_64-linux-gnu/libpython3.10.so";
                }

                PythonEngine.Initialize();
                PythonEngine.BeginAllowThreads();

                Console.WriteLine("Using Python DLL      : " + Runtime.PythonDLL);
                Console.WriteLine("Using Python version  : " + PythonEngine.Version);
                Console.WriteLine("Build information     : " + PythonEngine.BuildInfo);
                Console.WriteLine("Compiler              : " + PythonEngine.Compiler);
                Console.WriteLine("Max supported version : " + PythonEngine.MaxSupportedVersion);
                Console.WriteLine("Min supported version : " + PythonEngine.MinSupportedVersion);
                Console.WriteLine("Platform              : " + PythonEngine.Platform);
                Console.WriteLine("Program name          : " + PythonEngine.ProgramName);
                Console.WriteLine("Python home           : " + PythonEngine.PythonHome);
                Console.WriteLine("Python path           : " + PythonEngine.PythonPath);

                using (Py.GIL())
                {
                    dynamic app = Py.Import(script);
                    Console.WriteLine(app.multiply(2, 4));
                }
            }
            catch (Exception e)
            {
                Console.WriteLine(e.ToString());
            }
        }
    }
}

Файл script.py

def multiply(a, b):
  return a * b

Файл __init__.py

from script import multiply

Оба этих файла копируются в выходной каталог (например, bin/Debug/net8.0.

Работает в Windows:

C:\Code\Misc\PythonLoader\PythonLoader\bin\Debug\net8.0>pythonloader
Module name:  [script]
Using Python DLL      : C:\Python312\python312.dll
Using Python version  : 3.12.2 (tags/v3.12.2:6abddd9, Feb  6 2024, 21:26:36) [MSC v.1937 64 bit (AMD64)]
Build information     : tags/v3.12.2:6abddd9, Feb  6 2024, 21:26:36
Compiler              : [MSC v.1937 64 bit (AMD64)]
Max supported version : 3.12.2147483647.2147483647
Min supported version : 3.7
Platform              : win32
Program name          : python
Python home           :
Python path           : C:\Python312\python312.zip;C:\Python312\DLLs;C:\Python312\Lib;C:\Code\Misc\PythonLoader\PythonLoader\bin\Debug\net8.0
8

Не работает в Ubuntu:

joel@ubuntu:~/Code/pythontest/bin/Debug/net8.0$ ./pythontest
Python filename:  [script.py] 
Using Python DLL      : /usr/lib/x86_64-linux-gnu/libpython3.10.so
Using Python version  : 3.10.12 (main, Nov 20 2023, 15:14:05) [GCC 11.4.0]
Build information     : main, Nov 20 2023, 15:14:05
Compiler              : [GCC 11.4.0]
Max supported version : 3.12.2147483647.2147483647
Min supported version : 3.7
Platform              : linux
Program name          : python3
Python home           : 
Python path           : /usr/lib/python310.zip:/usr/lib/python3.10:/usr/lib/python3.10/lib-dynload:/home/joel/Code/pythontest/bin/Debug/net8.0
Python.Runtime.PythonException: No module named 'script'
   at Python.Runtime.PythonException.ThrowLastAsClrException()
   at Python.Runtime.NewReferenceExtensions.BorrowOrThrow(NewReference& reference)
   at Python.Runtime.PyModule.Import(String name)
   at Python.Runtime.Py.Import(String name)
   at PythonLoader.Program.Main(String[] args) in /home/joel/Code/pythontest/Program.cs:line 59

Содержимое каталога в Windows:

C:\Code\Misc\PythonLoader\PythonLoader\bin\Debug\net8.0>dir
 Volume in drive C is OS
 Volume Serial Number is 541C-D54E

 Directory of C:\Code\Misc\PythonLoader\PythonLoader\bin\Debug\net8.0

05/24/2024  08:34 PM    <DIR>          .
05/24/2024  09:07 AM    <DIR>          ..
01/11/2024  11:37 AM           322,048 GetSomeInput.dll
10/11/2023  12:15 AM           431,616 Python.Runtime.dll
05/24/2024  02:32 PM             7,378 PythonLoader.deps.json
05/24/2024  08:34 PM             6,656 PythonLoader.dll
05/24/2024  08:34 PM           142,848 PythonLoader.exe
05/24/2024  08:34 PM            10,932 PythonLoader.pdb
05/24/2024  09:17 AM               268 PythonLoader.runtimeconfig.json
05/24/2024  09:16 AM                37 script.py
05/24/2024  03:40 PM                29 __init__.py
05/24/2024  09:21 AM    <DIR>          __pycache__
               9 File(s)        921,812 bytes
               3 Dir(s)  48,029,245,440 bytes free

Содержимое каталога в Ubuntu:

joel@ubuntu:~/Code/pythontest/bin/Debug/net8.0$ ls -la
total 860
drwxrwxr-x 2 joel joel   4096 May 24 20:33 .
drwxrwxr-x 3 joel joel   4096 May 24 15:41 ..
-rwxrw-r-- 1 joel joel 322048 Jan 11 10:32 GetSomeInput.dll
-rw-rw-r-- 1 joel joel     31 May 24 15:52 __init__.py
-rwxrw-r-- 1 joel joel 431616 Oct 11  2023 Python.Runtime.dll
-rwxr-xr-x 1 joel joel  72448 May 24 20:33 pythontest
-rw-rw-r-- 1 joel joel   7171 May 24 15:41 pythontest.deps.json
-rw-rw-r-- 1 joel joel   6656 May 24 20:33 pythontest.dll
-rw-rw-r-- 1 joel joel  10964 May 24 20:33 pythontest.pdb
-rw-rw-r-- 1 joel joel    257 May 24 15:41 pythontest.runtimeconfig.json
-rw-rw-r-- 1 joel joel     38 May 24 20:31 script.py

Любая помощь приветствуется!

Обновлено: добавлено больше логов для подробностей и ясности.

Есть ли у eInnerException?

Tasos K. 27.05.2024 13:35

Привет @TasosK, я только что проверил, его нет.

joelc 27.05.2024 16:34
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
2
2
209
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Проблема, по-видимому, вызвана тем, что sys.path (пути поиска, используемые при загрузке модулей) не содержит текущий рабочий каталог при запуске в Linux (возможно, проблема в библиотеке).

Это можно определить, запустив простой скрипт:

import sys

print('; '.join(sys.path))

Поэтому нам нужно добавить текущий каталог в sys.path, чтобы наш скрипт мог загружать модули в текущем каталоге. Для этого нам просто нужно добавить пустую строку (как указано в документации, пустая строка означает текущий каталог) в этот массив.

Чтобы применить это, нам нужно немного отредактировать код и создать область видимости Python.

using (Py.GIL())
using (var scope = Py.CreateScope()) // Scope creation
{
    scope.Import("sys");
    // Line below is used just to check sys.path value. It can be removed
    Console.WriteLine(scope.Eval("'; '.join(sys.path)"));

    scope.Exec(@"if '' not in sys.path: sys.path.insert(0, '')"); // Add current directory to sys.path if not already there
    dynamic app = scope.Import(script); // Now import should work
    Console.WriteLine(app.multiply(2, 4));
}

Что ж, Маттео, ты сделал это снова. Спасибо. Это сработало как сон. Очень признателен.

joelc 29.05.2024 18:18

Другие вопросы по теме