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 childn"); execv( args[0], args ); } else { printf("I am the parentn"); 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 childn"); execv("/usr/bin/python",paramsList); } else { printf("I am the parentn"); 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 childn"); execv(args[0], args); } else { printf("I am the parentn"); 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.
Advertisement
Answer
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 childn"); execv(paramsList[0],paramsList); } else { printf("I am the parentn"); 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.