C和python子进程

时间:2018-03-04 22:49:26

标签: c subprocess pipe

我正在尝试让C进程创建一个python子进程,并使用两个并行FIFO双向通信。我也是分别读取python进程的标准输出(用于记录目的)。

计划是让Python和C程序完全独立运行,偶尔也会相互传递数据。

然而,我在使用从C到python的FIFO工作时遇到了很多麻烦,输出本身让我感到困惑。基本上我不知道为什么我的代码正在做它正在做的事情,我确信这是因为我根本不理解管道。

C代码:

int main() {
    printf("*** Starting main program ***\n");

    FILE *subprocOut = popen("python3 receiver.py", "r");

    // Make the fifo that we will write to and python will read
    const char *fifo1Name = "/tmp/demo1.fifo";
    int result = mkfifo(fifo1Name, S_IRWXU);
    if (result == 0) {
        printf("fifo1 successfully created!\n");
    }

    // Try to open fifo1
    FILE *fifo1 = fopen(fifo1Name, "w");
    if (fifo1) {
        printf("fifo1 successfully opened!\n");
    }

    // Try to open fifo2 (created and written to by python)
    const char *fifo2Name = "/tmp/demo2.fifo";
    FILE *fifo2 = fopen(fifo2Name, "r");
    if (fifo2) {
        printf("fifo2 successfully opened!\n");
    }

    // Various buffers
    const int bufSize = 1024;
    char buf1[bufSize]; // Used to read stdout of python process
    char buf2[bufSize]; // Used to read fifo2

    int running = 1;
    while (running) {
        printf("running...\n");

        // Write to the fifo (will be read by python script)
        const char* message = "Greetings from C!\n";
        fwrite(message, sizeof(char), strlen(message), fifo1);

        // Read from the fifo (contains output from python script)
        fread(buf2, sizeof(char), bufSize, fifo2);

        // Print the fifo output from python
        printf("[FIFO] %s\n", buf2);

        // Get the stdout of the python process
        if (fgets(buf1, bufSize, subprocOut) != NULL) {
            for (int i = bufSize; i >= 0; i--) {
                if (buf1[i] == '\n') {
                    buf1[i] = '\0';
                    break;
                }
            }

            printf("[PYTHON] %s\n", buf1);

            // If python printed a special token the whole program should terminate
            if (strncmp(buf1, "%TERMINATE%", bufSize) == 0) {
                running = 0;
            }
        }
    }

    // Close and delete both fifos

    fclose(fifo1);
    unlink(fifo1Name);

    fclose(fifo2);
    unlink(fifo2Name);

    printf("*** Terminating main program ***\n");
    return 0;
}

Python代码:

# Make fifo2
try:
    os.unlink('/tmp/demo2.fifo')
except FileNotFoundError:
    pass
os.mkfifo('/tmp/demo2.fifo')
print('fifo2 successfully created!')

# Open fifo1 (we will read from this)
fifo1 = open('/tmp/demo1.fifo', 'r')
print('fifo1 successfully opened!')

# Open fifo2 (we will write to this)
fifo2 = open('/tmp/demo2.fifo', 'w')
print('fifo2 successfully opened!')

sys.stdout.flush()

# Count how many seconds our program has been running
timeTaken = 0

while True:
    print('Running...')

    fifo2.write('hello!\n')

    # THESE LINES CAUSE PROGRAM TO HANG
    #
    # lines = fifo1.readlines()
    # for line in lines:
    #     print('RECEIVED:', line)

    sys.stdout.flush()

    # Pretend the sleep is caused by heavy computation
    time.sleep(1)
    timeTaken += 1

    # If we've been running for 3 seconds, pull the plug
    if timeTaken == 3:
        print('%TERMINATE%')
        break

输出:

*** Starting main program ***
fifo1 successfully opened!
fifo2 successfully opened!
running...
[FIFO] hello!
hello!
hello!

[PYTHON] fifo2 successfully created!
running...
[FIFO] hello!
hello!
hello!

[PYTHON] fifo1 successfully opened!
running...
[FIFO] hello!
hello!
hello!

[PYTHON] fifo2 successfully opened!
running...
[FIFO] hello!
hello!
hello!

[PYTHON] Running...
running...
[FIFO] hello!
hello!
hello!

[PYTHON] Running...
running...
[FIFO] hello!
hello!
hello!

[PYTHON] Running...
running...
[FIFO] hello!
hello!
hello!

[PYTHON] %TERMINATE%

Process finished with exit code 13

python代码中无限循环中注释掉的行会导致程序因某种原因挂起。我似乎无法读取从C到python的FIFO。

尽管在python中的无限循环之前调用了flush,但是与创建/打开管道有关的[PYTHON]输出与[FIFO]调用交错。

此外,hello!每次迭代时都会打印3次,即使它应该每次打印一次,就像[PYTHON] Running...一样。

此外,为什么{C}程序中running...的打印频率与[PYTHON] Running...一样频繁? python程序在循环的每次迭代中都会休眠一秒,但是C程序应该继续正确吗?是什么导致C中的主循环阻塞?

最后,我的C程序中的fclose()unlink()调用似乎导致了SIGPIPE信号,但是我应该如何关闭和删除FIFO呢?

0 个答案:

没有答案