如何从 C 程序 g_spawn (GLib) Python 脚本

How to g_spawn (GLib) a Python script from a C program

我正在尝试使用 GLib 从 C 程序中生成一个 python 脚本进程。当 Python 脚本已通过 PyInstaller 编译成可执行文件时,我可以轻松地执行此操作:

// Set the python executable string based on the OS
gchar* python_executable;

#ifdef __MSYS__
python_executable = "../gtk_simple_plot/dist/plot/plot.exe";
g_print("Using MSYS2\n");
#else
python_executable = "../gtk_simple_plot/dist/plot/./plot";
g_print("Not Using MSYS2\n");
#endif

// Create argv for the python executable
gchar* argv[] = {python_executable, NULL};

GPid transition_pid;
GError* err = NULL;

int stdoutFD;
int stderrFD;

// Spawn the python program to plot
g_spawn_async_with_pipes (NULL, // Inherit parent's working directory
argv,                           // argv from above
NULL,                           // Don't set any additional environment variables
G_SPAWN_DO_NOT_REAP_CHILD,      // Default spawn settings
NULL,                           // No setup function prior to executing
NULL,                           // No data passed to setup function
&transition_pid,                // Store child pid
NULL,                           // No standard input file descriptor
&stdoutFD,                      // Standard output file descriptor
&stderrFD,                      // Standard error file descriptor
&err);                          // Store error

if (err != NULL)
{
  g_error ("Spawning child failed: %s", err->message);
  return;
}

但是,我 运行 遇到了一些我认为来自 PyInstaller 的问题,所以我只想生成 Python 脚本,而不是可执行文件。我遇到的问题源于不知道要传递给 argv[] 的内容。生成进程上的 GLib 页面指出 g_spawn 系列函数的行为类似于跨平台 fork()exec():

https://developer.gnome.org/glib/stable/glib-Spawning-Processes.html

我发现这个 Stack Overflow link 说明了 argv[] 使用 execlp() 从 C 程序生成 Python 脚本的必要条件:

在那里,接受的答案指出参数应如下所示:

execlp("python3", "python3", "name_of_script.py", (char*)0);
//        ^ program to find
//                    ^ name to set in argv[0]
//                                  ^ script name to put in argv[1] so script is run

但是,我已经尝试了以下方法并且 none 有效:

(1) gchar* argv[] = {"python3 ../gtk_simple_plot/plot.py", NULL};
(2) gchar* argv[] = {"python3", "../gtk_simple_plot/plot.py", NULL};
(3) gchar* argv[] = {"python3", "../gtk_simple_plot/plot.py", (char*)0};
(4) gchar* argv[] = {"python3", "python3", "../gtk_simple_plot/plot.py", (char*)0};

全部导致相同的错误:

Spawning child failed: Failed to execute child process (No such file or directory)

显然我忽略了一些东西(可能很简单)。如有任何帮助,我们将不胜感激。

解决方案正在使用:

gchar* argv[] = {"python3", "../gtk_simple_plot/plot.py", NULL};

在默认生成设置中添加 G_SPAWN_SEARCH_PATH,这样 g_spawn 调用现在看起来像这样:

// Spawn the python program to plot
spawn_success = 
g_spawn_async_with_pipes (NULL,                     // Inherit parent's working directory
argv,                                               // argv from above
NULL,                                               // Don't set any additional environment variables
G_SPAWN_DO_NOT_REAP_CHILD | G_SPAWN_SEARCH_PATH,    // Default spawn settings
NULL,                                               // No setup function prior to executing
NULL,                                               // No data passed to setup function
&transition_pid,                                    // Store child pid
NULL,                                               // No standard input file descriptor
&stdoutFD,                                          // Standard output file descriptor
&stderrFD,                                          // Standard error file descriptor
&err);                                              // Store error

这个标志指定 argv[0] 不需要是绝对路径,它将在用户的 PATH.

中查找