运行 来自 Ada 程序的简单 Python 脚本
Running a simple Python script from Ada program
是否有人可以通过最简单的方法从 Ada 项目中 运行 Python 脚本?
本例中的 Python 脚本只有循环打印和睡眠,因此每次迭代都应打印参数。
我使用的Python脚本是
import sys
import time
for index in range(10):
print(sys.argv)
time.sleep(1)
我正在尝试的方法是 运行将此作为批处理脚本,因此使用
with Text_IO;
with Interfaces.C; use Interfaces.C;
procedure systest2 is
function Sys (Arg : Char_Array) return Integer;
pragma Import(C, Sys, "system");
Ret_Val : Integer;
begin
Ret_Val := Sys(To_C("python testpy.py arg1 arg2"));
end systest2;
问题是执行会阻塞脚本,这意味着 Python 打印输出仅在执行结束时立即打印。
我知道有一个基于 GNATCOLL 的解决方案(来自 Ada 的 运行 Python),但我找不到 运行 它的任何示例。
更新
澄清一下。
所以我会尽量简化这个问题。我想在 C:
中做同样的事情
#include <stdio.h>
#include <stdlib.h>
int main(){
system("python testpy.py ddddd");
return 0;
}
在这种情况下,它不会阻止 testpy.py 打印输出。
但我正在这样做
with Interfaces.C; use Interfaces.C;
procedure systest2 is
function Sys (Arg : Char_Array) return Integer;
pragma Import(C, Sys, "system");
Ret_Val : Integer;
begin
Ret_Val := Sys(To_C("python testpy.py arg1 arg2"));
end systest2;
阻止 testpy.py 脚本直到结束。这不应该发生。
那么,请问我该如何解决这个问题?
下面是一个可能有帮助的示例(在 Linux 上使用 GNAT CE 2019 进行了测试)。它基于 GNAT.Expect
包和 AdaCore's Gem articles 之一中给出的示例。在该示例中,生成了一个新进程并自动连接了管道。
两个备注:
运行 禁用 I/O 缓冲(使用 -u
选项)的 python 解释器很重要。如果这是不可取的,那么您也可以在 Python 3 中的 print
语句中使用 flush 选项,即 print(..., flush=True)
。如果您不禁用 I/O 缓冲或刷新 print
后面的 I/O 缓冲区,您将 运行 超时。
Python 脚本目前刚刚通过 Close
语句终止(它只是在 Linux 上发送 SIGKILL
信号) .
main.adb
with Ada.Text_IO; use Ada.Text_IO;
with GNAT.Expect; use GNAT.Expect;
with GNAT.OS_Lib; use GNAT.OS_Lib;
procedure Main is
Command : constant String := "python -u test.py 123";
Pd : Process_Descriptor;
Args : Argument_List_Access;
Result : Expect_Match;
begin
Args := Argument_String_To_List (Command);
Non_Blocking_Spawn
(Pd,
Command => Args (Args'First).all,
Args => Args (Args'First + 1 .. Args'Last),
Buffer_Size => 0);
for I in 1 .. 10 loop
Expect (Pd, Result, Regexp => "\d+", Timeout => 2_000);
case Result is
when Expect_Timeout =>
Put_Line ("Expect timed out.");
when 1 =>
Put_Line ("Received: " & Expect_Out_Match (Pd));
when others =>
raise Program_Error;
end case;
Put_Line ("Doing other stuff...");
end loop;
Close (Pd);
Free (Args);
exception
when Process_Died =>
Put_Line ("Process died.");
Close (Pd);
Free (Args);
end Main;
test.py
import sys
import time
while True:
print(sys.argv[1])
time.sleep(1)
输出
$ ./main
Received: 123
Doing other stuff...
Received: 123
Doing other stuff...
Received: 123
(repeated another 7 times).
是否有人可以通过最简单的方法从 Ada 项目中 运行 Python 脚本?
本例中的 Python 脚本只有循环打印和睡眠,因此每次迭代都应打印参数。
我使用的Python脚本是
import sys
import time
for index in range(10):
print(sys.argv)
time.sleep(1)
我正在尝试的方法是 运行将此作为批处理脚本,因此使用
with Text_IO;
with Interfaces.C; use Interfaces.C;
procedure systest2 is
function Sys (Arg : Char_Array) return Integer;
pragma Import(C, Sys, "system");
Ret_Val : Integer;
begin
Ret_Val := Sys(To_C("python testpy.py arg1 arg2"));
end systest2;
问题是执行会阻塞脚本,这意味着 Python 打印输出仅在执行结束时立即打印。
我知道有一个基于 GNATCOLL 的解决方案(来自 Ada 的 运行 Python),但我找不到 运行 它的任何示例。
更新
澄清一下。 所以我会尽量简化这个问题。我想在 C:
中做同样的事情#include <stdio.h>
#include <stdlib.h>
int main(){
system("python testpy.py ddddd");
return 0;
}
在这种情况下,它不会阻止 testpy.py 打印输出。
但我正在这样做
with Interfaces.C; use Interfaces.C;
procedure systest2 is
function Sys (Arg : Char_Array) return Integer;
pragma Import(C, Sys, "system");
Ret_Val : Integer;
begin
Ret_Val := Sys(To_C("python testpy.py arg1 arg2"));
end systest2;
阻止 testpy.py 脚本直到结束。这不应该发生。
那么,请问我该如何解决这个问题?
下面是一个可能有帮助的示例(在 Linux 上使用 GNAT CE 2019 进行了测试)。它基于 GNAT.Expect
包和 AdaCore's Gem articles 之一中给出的示例。在该示例中,生成了一个新进程并自动连接了管道。
两个备注:
运行 禁用 I/O 缓冲(使用
-u
选项)的 python 解释器很重要。如果这是不可取的,那么您也可以在 Python 3 中的print
语句中使用 flush 选项,即print(..., flush=True)
。如果您不禁用 I/O 缓冲或刷新print
后面的 I/O 缓冲区,您将 运行 超时。Python 脚本目前刚刚通过
Close
语句终止(它只是在 Linux 上发送SIGKILL
信号) .
main.adb
with Ada.Text_IO; use Ada.Text_IO;
with GNAT.Expect; use GNAT.Expect;
with GNAT.OS_Lib; use GNAT.OS_Lib;
procedure Main is
Command : constant String := "python -u test.py 123";
Pd : Process_Descriptor;
Args : Argument_List_Access;
Result : Expect_Match;
begin
Args := Argument_String_To_List (Command);
Non_Blocking_Spawn
(Pd,
Command => Args (Args'First).all,
Args => Args (Args'First + 1 .. Args'Last),
Buffer_Size => 0);
for I in 1 .. 10 loop
Expect (Pd, Result, Regexp => "\d+", Timeout => 2_000);
case Result is
when Expect_Timeout =>
Put_Line ("Expect timed out.");
when 1 =>
Put_Line ("Received: " & Expect_Out_Match (Pd));
when others =>
raise Program_Error;
end case;
Put_Line ("Doing other stuff...");
end loop;
Close (Pd);
Free (Args);
exception
when Process_Died =>
Put_Line ("Process died.");
Close (Pd);
Free (Args);
end Main;
test.py
import sys
import time
while True:
print(sys.argv[1])
time.sleep(1)
输出
$ ./main
Received: 123
Doing other stuff...
Received: 123
Doing other stuff...
Received: 123
(repeated another 7 times).