tags:

views:

78

answers:

5

I want to run a python script from another python script. Where I pass in variables as I would at command line.

So for example I would run my first script that would iterate thru a list of values 0,1,2,3 and past those to the 2nd script "script2.py 0" then "script2.py 1", etc.

I found SO 1186789 which is a similar question but ars's answer calls a function, where as I want to run the whole script not just a function. And balpha's answer calls the script but with no args. I altered this to something like the below as a test:

execfile("script2.py 1")

But is is not accept vars properly. When I print out the 'sys.argv' ins script2.py it is the original command call to first script "['C:\script1.py'].

I don't really want to change the original script (i.e. script2.py in my example) since I don't own it.

I figure there must be a way to do this just confuse as to how.

Thanks!

+3  A: 

Try using os.system:

os.system("script2.py 1")

execfile is different because it is designed to run a sequence of Python statements in the current execution context. That's why sys.argv didn't change for you.

Greg Hewgill
I believe it's generally preferable to use `subprocess.Popen` over `os.system`: http://docs.python.org/library/subprocess.html#replacing-os-system.
katrielalex
Yes, that's what the help for `os.system` says. However, for simple uses `os.system` is the simplest way to get the job done. It depends on what your needs are, of course.
Greg Hewgill
+1  A: 

SubProcess module:
http://docs.python.org/dev/library/subprocess.html#using-the-subprocess-module

import subprocess
subprocess.Popen("script2.py 1", shell=True)

With this, you can also redirect stdin, stdout, and stderr.

ChrisAdams
A: 

If os.system isn't powerful enough for you, there's the subprocess module.

Nathon
+5  A: 

This is inherently the wrong thing to do. If you are running a Python script from another Python script, you should communicate through Python instead of through the OS:

import script1

In an ideal world, you will be able to call a function inside script1 directly:

for i in range(whatever):
    script1.some_function(i)

If necessary, you can hack sys.argv. There's a neat way of doing this using a context manager to ensure that you don't make any permanent changes.

import contextlib
@contextlib.contextmanager
def redirect_argv(num):
    sys._argv = sys.argv[:]
    sys.argv=[str(num)]
    yield
    sys.argv = sys._argv

with redirect_argv(1):
    print(sys.argv)

I think this is preferable to passing all your data to the OS and back; that's just silly.

katrielalex
A: 

Ideally, the Python script you want to run will be set up with code like this near the end:

def main(arg1, arg2, etc):
    # does whatever the script does


if __name__ == "__main__":
    main(sys.argv[1], sys.argv[2], sys.argv[3])

In other words, if the module is called from the command line, it parses the command line options and then calls another function, main(), to do the actual work. (The actual arguments will vary, and the parsing may be more involved.)

If you want to call such a script from another Python script, however, you can simply import it and call modulename.main() directly, rather than going through the operating system.

os.system will work, but it is the roundabout (read "slow") way to do it, as you are starting a whole new Python interpreter process each time for no raisin.

kindall