简体   繁体   English

从 Ada 程序运行一个简单的 Python 脚本

[英]Running a simple Python script from Ada program

Does someone would have a simplest as possible way to run a Python script from the Ada project?有人会以最简单的方式从 Ada 项目运行 Python 脚本吗?

The Python script in this case only has a print in a loop, with a sleep, so each iteration it should print the arguments.在这种情况下,Python 脚本只有一个循环打印,带有睡眠,所以每次迭代它都应该打印 arguments。

The Python script I'm using is我正在使用的 Python 脚本是

import sys
import time

for index in range(10):
    print(sys.argv)
    time.sleep(1)

On approach I am trying is running this one as a batch script, so using我正在尝试的方法是将这个作为批处理脚本运行,所以使用

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;

The problem is that the execution blocks the script, meaning that the Python printouts are only printed at the end of the execution, at once.问题是执行阻塞了脚本,这意味着 Python 打印输出仅在执行结束时立即打印。

I know that there is a solution (to run Python from Ada) based on GNATCOLL, but I couldn't find any example to run it.我知道有一个基于 GNATCOLL 的解决方案(从 Ada 运行 Python),但我找不到任何示例来运行它。

Update更新

Just to clarify.只是为了澄清。 So I will try to simplify a bit the question.所以我会尽量简化这个问题。 I want to do the equivalent of this in C:我想在 C 中做同样的事情:

#include <stdio.h>
#include <stdlib.h>
int main(){
  system("python testpy.py ddddd");
  return 0;
}

In this case it does not block the testpy.py printouts.在这种情况下,它不会阻止 testpy.py 打印输出。

But I am doing this但我正在这样做

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;

which blocks the testpy.py script until its end.这会阻止 testpy.py 脚本直到它结束。 This should not happen.这不应该发生。

So, please, how could I fix this?那么,请问,我该如何解决这个问题?

Below is an example that might help (tested with GNAT CE 2019 on Linux).下面是一个可能有帮助的示例(在 Linux 上使用 GNAT CE 2019 进行了测试)。 It's based on the GNAT.Expect package and the example that was given in one of AdaCore's Gem articles .它基于GNAT.Expect package 和AdaCore 的 Gem 文章之一中给出的示例。 In the example, a new process is spawned and pipes are automatically connected.在示例中,生成了一个新进程并自动连接了管道。

Two remarks:两个备注:

  • It's important to run the python interpreter with I/O buffering disabled (using the -u option).在禁用 I/O 缓冲(使用-u选项)的情况下运行 python 解释器很重要。 If this is undesirable, then you can, alternatively, also use the flush option on the print statement in Python 3 ie print(..., flush=True) .如果这是不可取的,那么您也可以在 Python 3 中的print语句上使用 flush 选项,即print(..., flush=True) When you don't disable the I/O buffering or flush the I/O buffer behind print , you will run into timeouts.如果您不禁用 I/O 缓冲或在print后面刷新 I/O 缓冲区,您将遇到超时。

  • The Python script is, for now, just killed via the Close statement (it just sends the SIGKILL signal on Linux). 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测试.py

import sys
import time

while True:

    print(sys.argv[1])
    time.sleep(1)

output output

$ ./main
Received: 123
Doing other stuff...
Received: 123
Doing other stuff...
Received: 123

(repeated another 7 times).

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM