0

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.

2
  • /python -c expects the next argument to be a Python statement to execute. /usr/bin/python is not a valid Python statement. Commented Nov 2, 2021 at 15:38
  • Is bin/bash correct for the first line, and after -c the Python program to call? I just changed the file so that the Python program (with path) is the first arg -- no errors but it did not execute the Python program. Commented Nov 2, 2021 at 15:43

1 Answer 1

1

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.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.