Home > database >  Syntax error calling Python from C with fork-execv
Syntax error calling Python from C with fork-execv

Time:11-03

I want to call a Python script as a child process from a C program using fork and execv. I have tested it calling bin/ls and it works:

#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <stdio.h>

int main()
{
    int status;
    char *args[2];

    args[0] = "/bin/ls"; 
    args[1] = NULL; 

    if ( fork() == 0 ){
        printf("I am the child\n");
        execv( args[0], args ); }
    else {
        printf("I am the parent\n");
        wait( &status ); }

    return 0;
}

So I changed the C code to call the Create_Buffer() function in this Python file:

#!/usr/bin/python3

from nltk.corpus import gutenberg

def Create_Buffer():

    out_buf = []
    pointer = id(out_buf)

    value_in = 21

    print("I was here")
    print(value_in)

    return pointer

def NLTK_Python_Libs(n):

    if n == 0:
        n = n   1
        return id(n)

The Python script has two functions; I want to call Create_Buffer(), so I changed my C file to:

#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <stdio.h>

int main()
{
    int status;
    char * paramsList[] = { "/bin/bash", "-c", "/usr/bin/python",   "/opt/P01_SH/NLTK_Gutenberg/NLTK_Python_Libs.Create_Buffer()", (char *)NULL };

    if ( fork() == 0 ){
        printf("I am the child\n");
        execv("/usr/bin/python",paramsList); }
    else {
        printf("I am the parent\n");
        wait( &status ); }

    return 0;
}

But I get a syntax error when I run it:

I am the parent

I am the child

File "string", line 1

/usr/bin/python

SyntaxError: invalid syntax

Next I changed it slightly, but I got a different error (described below):

#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <stdio.h>

int main()
{
    int status;
    char *args[5];
    args[0] = "/bin/bash";
    args[1] = "-c";
    args[2] = "/usr/bin/python";
    args[3] =   "/opt/P01_SH/NLTK_Gutenberg/NLTK_Python_Libs.Create_Buffer()"; 
    args[4] = NULL;

    if ( fork() == 0 ){
        printf("I am the child\n");
        execv(args[0], args); }
    else {
        printf("I am the parent\n");
        wait( &status ); }

    return 0;
}

And this time it invoked the Python command line instead of calling the program:

I am the parent

I am the child

Python 3.8.0 (default, Feb 25 2021, 22:10:10)

[GCC 8.4.0] on linux

Type "help", "copyright", "credits" or "license" for more information.

[ Python command prompt ]

The errors seem to implicate the shebang line at the top of the Python file, but I get the same errors whether I use #!/usr/bin/python, #!/usr/bin/python3 or #!/usr/bin/env python3, or leave the shebang line out.

So my question is: how do I specify the arguments for fork-execv when I want to call a program in a Python .py file? I'm open to using any of the other exec* family, except that I want to use the absolute path, as above, rather than adding to Python PATH, so I don't want to use exec calls with "p" in the name.

I have researched extensively but I haven't found any examples that show the syntax to call a specific program within a Python file and pass arguments to the program. I have seen examples calling a Python file without specifying a program within the file and without passing arguments, but I need to call the function by name.

Compile the C program with:

gcc -fPIC -ggdb -o NLTK_Python.exe NLTK_Python.c -Wall -Wextra

I'm using Python 3.8 on Ubuntu 18.04.

Thanks for any help with this.

CodePudding user response:

I think this is what you want:

#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <stdio.h>

int main()
{
    int status;
    char * paramsList[] = {
        "/usr/bin/python",
            "-m",
            "NLTK_Python_Libs",
            "-c",
            "NLTK_Python_Libs.Create_Buffer()",
            (char *)NULL };

    if ( fork() == 0 ){
        printf("I am the child\n");
        execv(paramsList[0],paramsList); }
    else {
        printf("I am the parent\n");
        wait( &status ); }

    return 0;
}

The -m option tells it to load the NLTK_Python_Libs module. Then -c tells it to execute a function from that module. You can't combine the script pathname with the function name to execute the way you did.

There's no need to use /bin/bash at all. Just execute python directly.

  • Related