Проблема с взаимодействием с питоном через pipe () вызов C - PullRequest
1 голос
/ 05 апреля 2019

Я пытаюсь написать C-программу для Linux, которая могла бы взаимодействовать с другими программами с помощью вызовов pipe (). Следующий код не работает, однако точно так же работает, если я изменяю "/ usr / bin / python" на "/ bin / cat" (я имею в виду, строка распечатывается)

#include <unistd.h>
#include <sys/prctl.h>
#include <signal.h>

int main()
{
        int inpipe[2], outpipe[2], pid, in_bytes;
        char *cmd[] = {"python", (char *) NULL}, buff[1024];
        pipe(inpipe);
        pipe(outpipe);

        pid = fork();
        if (pid == 0)
        {
                dup2(inpipe[1], 1);
                dup2(inpipe[1], 2);
                dup2(outpipe[0], 0);

                prctl(PR_SET_PDEATHSIG, SIGTERM);

                execve("/usr/bin/python", cmd, NULL);
        }
        close(inpipe[1]);
        close(outpipe[0]);

        write(outpipe[1], "print \"lol\"\n", 12);
        in_bytes = read(inpipe[0], buff, 1024);
        write(1, buff, in_bytes);

        close(inpipe[0]);
        close(outpipe[1]);
        return 0;
}

1 Ответ

0 голосов
/ 05 апреля 2019

Проблема в том, что python ведет себя как REPL по умолчанию только тогда, когда ввод tty. Без tty это просто REP:

# Hangs until the pipe is closed with Ctrl+D
{ echo 'print "lol"'; cat; } | python

У вас есть несколько вариантов в зависимости от того, что вы хотите сделать. Два из них включают в себя:

  1. Запустите python -i, чтобы получить REPL (char *cmd[] = {"python", "-i", (char *) NULL}). Это покажет все интерактивные подсказки и тому подобное, так что вам придется читать больше данных.

  2. Закройте канал, чтобы Python знал, что скрипт выполнен. Это заставит его выполнить его.

Вот ваш код, адаптированный для этого:

#include <unistd.h>
#include <sys/prctl.h>
#include <signal.h>

int main()
{
        int inpipe[2], outpipe[2], pid, in_bytes;
        char *cmd[] = {"python", (char *) NULL}, buff[1024];
        pipe(inpipe);
        pipe(outpipe);

        pid = fork();
        if (pid == 0)
        {
                dup2(inpipe[1], 1);
                dup2(inpipe[1], 2);
                dup2(outpipe[0], 0);
                close(outpipe[0]);
                close(outpipe[1]);

                prctl(PR_SET_PDEATHSIG, SIGTERM);

                execve("/usr/bin/python", cmd, NULL);
        }
        close(inpipe[1]);
        close(outpipe[0]);

        write(outpipe[1], "print \"lol\"\n", 12);
        close(outpipe[1]);
        in_bytes = read(inpipe[0], buff, 1024);
        write(1, buff, in_bytes);

        close(inpipe[0]);
        close(outpipe[1]);
        return 0;
}
...