465

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
wjandrea
  • 28,235
  • 9
  • 60
  • 81
Josh Smeaton
  • 47,939
  • 24
  • 129
  • 164
  • 59
    The better way is to write methods and classes and use them – Aamir Jul 27 '09 at 07:00
  • 1
    related: [Python 3: Call python script with input with in a python script using subprocess](http://stackoverflow.com/q/30076185/4279) – jfs Nov 29 '15 at 08:40
  • See this answer: https://stackoverflow.com/a/71967141/1364242 – Jay M Apr 22 '22 at 10:20

17 Answers17

373

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()
ars
  • 120,335
  • 23
  • 147
  • 134
  • 67
    What if `test1.py` is located in some far-away directory? – Evgeni Sergeev Jun 08 '14 at 05:46
  • 5
    @EvgeniSergeev See http://stackoverflow.com/questions/67631/how-to-import-a-module-given-the-full-path – Evgeni Sergeev Jun 08 '14 at 06:27
  • 61
    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. – gented Mar 22 '17 at 10:36
  • 12
    @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. – martineau Nov 06 '17 at 17:15
  • 6
    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. – gented Nov 06 '17 at 20:29
  • while using this solution i am facing issue while executing the`response.json()` statement in one of the function of the imported script. executing the imported script separately works fine at `response.json()`. error encountered is `json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)` – Bikiran Das Nov 21 '19 at 13:42
228

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.

wjandrea
  • 28,235
  • 9
  • 60
  • 81
balpha
  • 50,022
  • 18
  • 110
  • 131
  • 12
    This approach executes the scripts within the calling namespace. :) – dmvianna Oct 21 '13 at 05:46
  • 9
    to pass command-line arguments to the script, you could edit `sys.argv` list. – jfs Jan 13 '15 at 18:09
  • 1
    More comprehensive treatment on Python 3 equivalents: http://stackoverflow.com/questions/436198/what-is-an-alternative-to-execfile-in-python-3-0 – John Y Aug 04 '16 at 15:38
  • 5
    This does not accept arguments (to be passed to the PY file)! – Apostolos Sep 13 '18 at 10:43
  • I want it to compile the `.py` into a `.pyc` so subsequent executions are faster. I take it this will not work for that? Basically I want to import the entire script like a module and then run the main within it. – WinEunuuchs2Unix Apr 28 '21 at 23:00
  • I read a lot of "never ever use ```exec```" warnings online. What's the matter here? Say, I want to split up one script into several files so I don't have to scroll a lot. Can I now ```exec``` one file from another when the manual alternative would be: go to other file [strg] + [a], [F9]? Using the same namespace is **exactly** what I want. Any concerns? – Manuel Popp Jun 29 '21 at 11:03
  • Using this with pytest, it cause `NameError: name ... is not defined`. – Muhammad Yasirroni Nov 03 '22 at 04:25
124

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

Jacktose
  • 709
  • 7
  • 21
Dick Goodwin
  • 1,249
  • 1
  • 8
  • 2
  • 9
    I had to use `subprocess.call("./test1.py", shell=True)` to make it work – asmaier Apr 17 '13 at 09:45
  • 8
    Do not use `shell=True` unless it's necessary. – Piotr Dobrogost Nov 03 '13 at 10:58
  • 5
    @PiotrDobrogost - Could you specify which situations would make it necessary? – sancho.s ReinstateMonicaCellio Dec 26 '13 at 13:12
  • @sancho.s For instance when you have rather complex bash command and you don't want to *translate* it to Python code. – Piotr Dobrogost Dec 27 '13 at 21:22
  • 9
    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](http://stackoverflow.com/a/22881871/4279). – jfs Jan 13 '15 at 18:14
  • 1
    I had to use subprocess.call("Python test1.py", shell=True) to make it work as the default program to open a "py" file is Notepad instead of Python.exe on my workstation. – alextc Jan 27 '15 at 02:39
  • that's great but it works with python 2.4+ .. how about the ppl who must use python 2.1 – Deian Mar 13 '15 at 20:08
  • 2
    `shell=True` is fine as long as the shell command being run is not formed from user input. Otherwise it risks shell injection. – Pavin Joseph Dec 04 '17 at 10:55
  • 1
    Should it have `subprocess.call("python test1.py", shell=True)` instead. – Nitish Kumar Pal Jan 07 '18 at 08:05
  • 12
    Or `subprocess.call(['python', 'test1.py'])`. – Big McLargeHuge Mar 06 '18 at 16:06
  • 3
    @NitishKumarPal No; as already pointed out in earlier comments, you should avoid `shell=True` when you can. There is no shell functionality here so `subprocess.call(['python', 'test1.py'])` is definitely better, though you should probably use `check_call` or `run` instead (or not run Python as a subprocess of Python). See also https://stackoverflow.com/questions/3172470/actual-meaning-of-shell-true-in-subprocess – tripleee Sep 04 '19 at 07:46
  • So `subprocess.call(['python', 'test1.py']`, just in case the file extension has no association to `python` or `python3`. – Andrew Jul 11 '23 at 08:02
39
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)
Alex Mapley
  • 752
  • 8
  • 12
  • calls to `os.system` should be avoided, you can do the same with any Class from `Popen, Call, ` – user1767754 Jan 05 '18 at 04:45
  • 3
    From the [Python documentation](https://docs.python.org/2/library/os.html#os.system): The subprocess module provides more powerful facilities for spawning new processes and retrieving their results; using that module is preferable to using this function. – Big McLargeHuge Mar 06 '18 at 15:48
  • 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. – Alex Mapley Aug 11 '23 at 21:17
31

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
Michael Schneider
  • 17,929
  • 3
  • 24
  • 14
26

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')

Flavio
  • 759
  • 1
  • 11
  • 24
  • This answer should be higher up. – Lu Kas Oct 26 '22 at 21:54
  • 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. – laimison Nov 09 '22 at 23:51
14

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()
thedz
  • 5,496
  • 3
  • 25
  • 29
  • 4
    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? – NULL.Dude Apr 03 '18 at 19:50
10

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')
Community
  • 1
  • 1
gimel
  • 83,368
  • 10
  • 76
  • 104
  • 3
    `reload` is gone in Python 3. – Piotr Dobrogost Nov 03 '13 at 10:59
  • 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](http://stackoverflow.com/a/1186847/4279) instead – jfs Jan 13 '15 at 18:18
  • @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. – MattSt Jun 11 '22 at 16:17
5

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.

Chao Chen
  • 71
  • 1
  • 4
4

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.

xcrafter_40
  • 107
  • 1
  • 10
Anurag Uniyal
  • 85,954
  • 40
  • 175
  • 219
  • 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? – WinEunuuchs2Unix Apr 28 '21 at 23:08
3

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.

Dharman
  • 30,962
  • 25
  • 85
  • 135
3

An example to do it using subprocess.

from subprocess import run
import sys 
run([sys.executable, 'fullpathofyourfile.py'])
eng
  • 443
  • 1
  • 4
  • 10
Maisum Abbas
  • 317
  • 1
  • 10
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)
2

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_)
Benyamin Jafari
  • 27,880
  • 26
  • 135
  • 150
  • 2
    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. – tripleee Sep 04 '19 at 07:44
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!

Ashwin Balani
  • 745
  • 7
  • 19
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 +.

Faraaz Kurawle
  • 1,085
  • 6
  • 24
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.

PV8
  • 5,799
  • 7
  • 43
  • 87
  • Your syntax is wrong for the Python3 print function. Python3 uses brackets to enclose the string. E.g. print("Hello World") – Shary Jun 21 '23 at 15:43