494

I have a script named test1.py which is not in a module. It just has code that should execute when the script itself is run. There are no functions, classes, methods, etc. I have another script which runs as a service. I want to call test1.py from the script running as a service.

For example:

File test1.py:

print "I am a test" print "see! I do nothing productive." 

File service.py:

# Lots of stuff here test1.py # do whatever is in test1.py 
4

17 Answers 17

385

The usual way to do this is something like the following.

test1.py

def some_func(): print 'in test 1, unproductive' if __name__ == '__main__': # test1.py executed as script # do something some_func() 

service.py

import test1 def service_func(): print 'service func' if __name__ == '__main__': # service.py executed as script # do something service_func() test1.some_func() 
Sign up to request clarification or add additional context in comments.

6 Comments

What if test1.py is located in some far-away directory?
This doesn't really answer the question though, does it? You aren't executing the whole script, you're executing some functions from within the script that you import.
@GennaroTedesco: You're mistaken. The import test1 in service.py does indeed execute the whole script (which only defines some_func() since __name__ == '__main__' will be False in that case). That sounds like all the OP wants to do. This answer goes beyond that, but definitely does answer the question—and then some.
If, say, test1.py didn't contain the definition of the function some_func() (but rather just some lines of code, for instance print("hello")) then your code wouldn't work. In this particular example it does work because you're essentially importing an external function that you are afterwards calling back.
|
246

This is possible in Python 2 using execfile:

execfile("test2.py") 

In Python 3, this is possible using exec:

exec(open("test2.py").read()) 

See the documentation for the handling of namespaces, if important in your case.

However, you should consider using a different approach; your idea (from what I can see) doesn't look very clean.

8 Comments

This approach executes the scripts within the calling namespace. :)
to pass command-line arguments to the script, you could edit sys.argv list.
More comprehensive treatment on Python 3 equivalents: stackoverflow.com/questions/436198/…
This does not accept arguments (to be passed to the PY file)!
Using this with pytest, it cause NameError: name ... is not defined.
|
134

Another way:

File test1.py:

print "test1.py" 

File service.py:

import subprocess subprocess.call("test1.py", shell=True) 

The advantage to this method is that you don't have to edit an existing Python script to put all its code into a subroutine.

Documentation: Python 2, Python 3

12 Comments

I had to use subprocess.call("./test1.py", shell=True) to make it work
Do not use shell=True unless it's necessary.
@PiotrDobrogost - Could you specify which situations would make it necessary?
It won't work on a typical Unix where the current directory is not in PATH. test1.py should be executable and have the shebang line (#!/usr/bin/env python) and you should specify the full path or you need to provide the executable yourself: call([sys.executable, os.path.join(get_script_dir(), 'test1.py')]) where get_script_dir() is defined here.
Or subprocess.call(['python', 'test1.py']).
|
44
import os os.system("python myOtherScript.py arg1 arg2 arg3") 

Using os you can make calls directly to your terminal. If you want to be even more specific you can concatenate your input string with local variables, ie.

command = 'python myOtherScript.py ' + sys.argv[1] + ' ' + sys.argv[2] os.system(command) 

3 Comments

calls to os.system should be avoided, you can do the same with any Class from Popen, Call,
From the Python documentation: The subprocess module provides more powerful facilities for spawning new processes and retrieving their results; using that module is preferable to using this function.
Agreed, the subprocess module is likely better if you want to do anything more complicated. os.system() is sometimes nice and easy if you just want the single call.
35

If you want test1.py to remain executable with the same functionality as when it's called inside service.py, then do something like:

test1.py

def main(): print "I am a test" print "see! I do nothing productive." if __name__ == "__main__": main() 

service.py

import test1 # lots of stuff here test1.main() # do whatever is in test1.py 

2 Comments

What if you have runtime parameters?
sys.argv can still be used here. And you can def main(*args), as needed
34

I prefer runpy:

#!/usr/bin/env python # coding: utf-8 import runpy runpy.run_path(path_name='script-01.py') runpy.run_path(path_name='script-02.py') runpy.run_path(path_name='script-03.py') 

2 Comments

When you import modules in a main script, same modules import in a child script is instant. So runpy has advantage over subprocess. This can be used eg to pre-load modules in advance for a better performance.
How would I provide argvs?
15

You should not be doing this. Instead, do:

test1.py:

 def print_test(): print "I am a test" print "see! I do nothing productive." 

service.py

#near the top from test1 import print_test #lots of stuff here print_test() 

1 Comment

when you import test1 how does it know where the file is? does it have to be in the same directory? what if its not?
12

Use import test1 for the 1st use - it will execute the script. For later invocations, treat the script as an imported module, and call the reload(test1) method.

When reload(module) is executed:

  • Python modules’ code is recompiled and the module-level code reexecuted, defining a new set of objects which are bound to names in the module’s dictionary. The init function of extension modules is not called

A simple check of sys.modules can be used to invoke the appropriate action. To keep referring to the script name as a string ('test1'), use the 'import()' builtin.

import sys if sys.modules.has_key['test1']: reload(sys.modules['test1']) else: __import__('test1') 

3 Comments

reload is gone in Python 3.
importing a module is not equivalent to running it e.g., consider if __name__ == "__main__": guard. There could be other more subtle differences. Don't leave arbitrary code at the global level. Put it in a function and call it after the import as suggested in the accepted answer instead
@PiotrDobrogost It's not. You just have to get it through the package 'imp' which now has to be imported explicitly, or through the package 'importlib'. Imp is deprecated in favour of importlib though.
6

Why not just import test1? Every python script is a module. A better way would be to have a function e.g. main/run in test1.py, import test1 and run test1.main(). Or you can execute test1.py as a subprocess.

1 Comment

Let's say I use import test1 because I want .py to compile to .pyc for next time. How do I pass my parameters to it? Will I main() function be run automatically or do I have to do something special in it?
6

As it's already mentioned, runpy is a nice way to run other scripts or modules from current script.

By the way, it's quite common for a tracer or debugger to do this, and under such circumstances methods like importing the file directly or running the file in a subprocess usually do not work.

It also needs attention to use exec to run the code. You have to provide proper run_globals to avoid import error or some other issues. Refer to runpy._run_code for details.

Comments

5

Add this to your python script.

import os os.system("exec /path/to/another/script") 

This executes that command as if it were typed into the shell.

Comments

5

An example to do it using subprocess.

from subprocess import run import sys run([sys.executable, 'fullpathofyourfile.py']) 

Comments

4

This is an example with subprocess library:

import subprocess python_version = '3' path_to_run = './' py_name = '__main__.py' # args = [f"python{python_version}", f"{path_to_run}{py_name}"] # works in python3 args = ["python{}".format(python_version), "{}{}".format(path_to_run, py_name)] res = subprocess.Popen(args, stdout=subprocess.PIPE) output, error_ = res.communicate() if not error_: print(output) else: print(error_) 

1 Comment

Running Python as a subprocess of Python is almost never the correct solution. If you do go with a subprocess, you should avoid Popen unless the higher-level functions really cannot do what you want. In this case, check_call or run would do everything you need and more, with substantially less plumbing in your own code.
3

I found runpy standard library most convenient. Why? You have to consider case when error raised in test1.py script, and with runpy you are able to handle this in service.py code. Both traceback text (to write error in log file for future investigation) and error object (to handle error depends on its type): when with subprocess library I wasn't able to promote error object from test1.py to service.py, only traceback output. Also, comparing to "import test1.py as a module" solution, runpy is better cause you have no need to wrap code of test1.py into def main(): function.

Piece of code as example, with traceback module to catch last error text:

import traceback import runpy #https://www.tutorialspoint.com/locating-and-executing-python-modules-runpy from datetime import datetime try: runpy.run_path("./E4P_PPP_2.py") except Exception as e: print("Error occurred during execution at " + str(datetime.now().date()) + " {}".format(datetime.now().time())) print(traceback.format_exc()) print(e) 

Comments

2

This process is somewhat un-orthodox, but would work across all python versions,

Suppose you want to execute a script named 'recommend.py' inside an 'if' condition, then use,

if condition: import recommend 

The technique is different, but works!

Comments

1

According to the given example, this is the best way:

# test1.py def foo(): print("hellow") 
# test2.py from test1 import foo # might be different if in different folder. foo() 

But according to the title, using os.startfile("path") is the best way as its small and it works. This would execute the file specified. My python version is 3.x +.

Comments

0

As I found this, when I was searching for a solution in python 3. In python 3 you can just use the importfunctions (note that the py.files should not have a name as a library, it should have a unique name):

File test1.py:

print "I am a test" print "see! I do nothing productive." 

File service.py:

import test1 

and if you only run the service.py it will generate the output:

"I am a test" "see! I do nothing productive." 

Note that it should be in the same repository/folder.

1 Comment

Your syntax is wrong for the Python3 print function. Python3 uses brackets to enclose the string. E.g. print("Hello World")

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.