How to call a script from another script?

Learn how to call a script from another script? with practical examples, diagrams, and best practices. Covers python development techniques with visual explanations.

Mastering Script Execution: Calling One Python Script from Another

Hero image for How to call a script from another script?

Learn various methods to execute a Python script from within another, understanding their implications for process control, data sharing, and environment management.

In Python development, it's a common requirement to organize code into modular scripts and then execute one script from within another. This approach promotes code reusability, improves project structure, and allows for complex workflows to be broken down into manageable components. This article explores several robust methods for calling a Python script from another, detailing their use cases, advantages, and potential pitfalls.

Understanding the Need for Inter-Script Communication

Before diving into the 'how,' it's crucial to understand 'why' you might need one script to call another. Common scenarios include:

  • Modularity: Breaking down a large application into smaller, focused scripts.
  • Workflow Orchestration: A main script coordinating the execution of several sub-tasks.
  • Resource Management: Running a script that sets up an environment, then executing another that performs the core logic.
  • Testing: Automating the execution of test scripts from a test runner.
flowchart TD
    A[Main Script] --> B{"Call Method?"}
    B -->|Import| C[Sub-script as Module]
    B -->|Subprocess| D[Sub-script as Separate Process]
    B -->|Exec/Popen| E[Sub-script as External Command]
    C --> F[Function/Class Call]
    D --> G[Independent Execution]
    E --> H[Shell Command Execution]
    F & G & H --> I[Result/Output]

Decision flow for calling one Python script from another.

Method 1: Importing as a Module

The most Pythonic and generally recommended way to reuse code from another script is to treat it as a module. This involves importing the script and then calling its functions or accessing its variables directly. For this to work effectively, the called script should be designed with functions or classes that encapsulate its logic, rather than having top-level executable code.

# sub_script.py
def greet(name):
    return f"Hello, {name}!"

def calculate_sum(a, b):
    return a + b

if __name__ == "__main__":
    print("This code runs only when sub_script.py is executed directly.")
    print(greet("World"))

Example of sub_script.py designed for modular import.

# main_script.py
import sub_script

message = sub_script.greet("Alice")
print(message)

result = sub_script.calculate_sum(10, 20)
print(f"The sum is: {result}")

Calling sub_script.py as a module from main_script.py.

Method 2: Using subprocess Module

When you need to run another script as a completely separate process, perhaps to isolate its environment, capture its output, or run it concurrently, the subprocess module is the ideal choice. This method treats the called script as an external command, similar to running it from the command line. It's particularly useful for running scripts that are not designed as modules or for executing scripts written in other languages.

# another_script.py
import sys

if len(sys.argv) > 1:
    name = sys.argv[1]
    print(f"Hello from another_script.py, {name}!")
else:
    print("Hello from another_script.py!")

print("This is some output from another_script.py.")

Example of another_script.py that accepts command-line arguments.

# main_caller.py
import subprocess
import sys

# Method 1: Simple call, waits for completion
print("\n--- Calling another_script.py without arguments ---")
subprocess.run([sys.executable, 'another_script.py'])

# Method 2: Calling with arguments and capturing output
print("\n--- Calling another_script.py with arguments and capturing output ---")
result = subprocess.run(
    [sys.executable, 'another_script.py', 'Bob'],
    capture_output=True, text=True, check=True
)
print("STDOUT:", result.stdout)
print("STDERR:", result.stderr)

# Method 3: Running in the background (non-blocking)
print("\n--- Calling another_script.py in the background ---")
process = subprocess.Popen([sys.executable, 'another_script.py', 'Charlie'])
# Do other things while another_script.py runs
# process.wait() # Uncomment to wait for completion
print("Main script continues execution...")

Using subprocess.run and subprocess.Popen to execute another script.

Method 3: Using exec() or execfile() (Python 2)

The exec() function (and execfile() in Python 2) allows you to execute Python code dynamically. While powerful, it's generally discouraged for calling other scripts due to security risks and difficulty in debugging. It executes the code in the current namespace, which can lead to unexpected variable overwrites or scope issues. Use this method with extreme caution and only when other options are not viable.

# dynamic_script.py
my_variable = "I am from dynamic_script.py"
def dynamic_function():
    print("Hello from dynamic_function!")

A simple script to be executed dynamically.

# main_dynamic_caller.py
# This method is generally discouraged for inter-script calls.

print("Before exec:")
try:
    print(my_variable) # This will raise a NameError
except NameError as e:
    print(f"Error: {e}")

with open('dynamic_script.py', 'r') as f:
    code = f.read()
    exec(code)

print("\nAfter exec:")
print(my_variable)
dynamic_function()

Demonstrating exec() to run another script's content.