Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Run a python script with arguments

Tags:

python

c

eclipse

I want to call a Python script from C, passing some arguments that are needed in the script.

The script I want to use is mrsync, or multicast remote sync. I got this working from command line, by calling:

python mrsync.py -m /tmp/targets.list -s /tmp/sourcedata -t /tmp/targetdata

-m is the list containing the target ip-addresses. -s is the directory that contains the files to be synced. -t is the directory on the target machines where the files will be put.

So far I managed to run a Python script without parameters, by using the following C program:

Py_Initialize();
FILE* file = fopen("/tmp/myfile.py", "r");
PyRun_SimpleFile(file, "/tmp/myfile.py");
Py_Finalize();

This works fine. However, I can't find how I can pass these argument to the PyRun_SimpleFile(..) method.

like image 807
Bram W. Avatar asked Aug 27 '12 12:08

Bram W.


2 Answers

Seems like you're looking for an answer using the python development APIs from Python.h. Here's an example for you that should work:

#My python script called mypy.py
import sys

if len(sys.argv) != 2:
  sys.exit("Not enough args")
ca_one = str(sys.argv[1])
ca_two = str(sys.argv[2])

print "My command line args are " + ca_one + " and " + ca_two

And then the C code to pass these args:

//My code file
#include <stdio.h>
#include <python2.7/Python.h>

void main()
{
    FILE* file;
    int argc;
    char * argv[3];

    argc = 3;
    argv[0] = "mypy.py";
    argv[1] = "-m";
    argv[2] = "/tmp/targets.list";

    Py_SetProgramName(argv[0]);
    Py_Initialize();
    PySys_SetArgv(argc, argv);
    file = fopen("mypy.py","r");
    PyRun_SimpleFile(file, "mypy.py");
    Py_Finalize();

    return;
}

If you can pass the arguments into your C function this task becomes even easier:

void main(int argc, char *argv[])
{
    FILE* file;

    Py_SetProgramName(argv[0]);
    Py_Initialize();
    PySys_SetArgv(argc, argv);
    file = fopen("mypy.py","r");
    PyRun_SimpleFile(file, "mypy.py");
    Py_Finalize();

    return;
}

You can just pass those straight through. Now my solutions only used 2 command line args for the sake of time, but you can use the same concept for all 6 that you need to pass... and of course there's cleaner ways to capture the args on the python side too, but that's just the basic idea.

Hope it helps!

like image 119
Mike Avatar answered Oct 21 '22 01:10

Mike


You have two options.

  1. Call

    system("python mrsync.py -m /tmp/targets.list -s /tmp/sourcedata -t /tmp/targetdata")
    

    in your C code.

  2. Actually use the API that mrsync (hopefully) defines. This is more flexible, but much more complicated. The first step would be to work out how you would perform the above operation as a Python function call. If mrsync has been written nicely, there will be a function mrsync.sync (say) that you call as

    mrsync.sync("/tmp/targets.list", "/tmp/sourcedata", "/tmp/targetdata")
    

    Once you've worked out how to do that, you can call the function directly from the C code using the Python API.

like image 26
Katriel Avatar answered Oct 21 '22 01:10

Katriel