python
scripting
argument-passing
code-integration
duplicate-question

Run a Python script from another Python script, passing in arguments

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

Introduction

Running one Python script from another is common in automation, orchestration, and CLI wrappers. The right solution depends on whether you truly need a separate process. If you do, subprocess with an explicit argument list is the safe default because it gives you correct quoting, exit codes, output capture, and timeout control.

Decide Whether You Need a New Process

Before spawning another script, ask whether importing a function would be better.

Use an import when:

  • you control both files
  • you want direct return values
  • you do not need process isolation

Use a child process when:

  • the second script is an independent command-line tool
  • it should run with its own process state
  • you need a separate exit code or timeout boundary

If the child logic is really just reusable code, refactoring it into a module is usually cleaner than making one script shell out to another.

Use subprocess.run with an Argument List

The safe pattern is to pass a list of arguments rather than building one shell command string.

python
1import subprocess
2import sys
3
4result = subprocess.run(
5    [sys.executable, "child.py", "--name", "Ana", "--count", "3"],
6    capture_output=True,
7    text=True,
8    check=False,
9)
10
11print("exit code:", result.returncode)
12print("stdout:", result.stdout)
13print("stderr:", result.stderr)

sys.executable is important because it uses the current Python interpreter, which is especially useful in virtual environments. Passing a list instead of a shell string avoids quoting bugs and reduces injection risk.

Parse the Child Arguments with argparse

The parent process is only half of the design. The child script should define a clear interface too.

python
1import argparse
2
3parser = argparse.ArgumentParser()
4parser.add_argument("--name", required=True)
5parser.add_argument("--count", type=int, default=1)
6args = parser.parse_args()
7
8for _ in range(args.count):
9    print(f"hello {args.name}")

This makes the boundary between parent and child explicit. Once both scripts treat the interaction as a small CLI contract, debugging gets much easier.

Handle Failures and Timeouts

Production code should not assume the child succeeds or finishes quickly.

python
1import subprocess
2import sys
3
4try:
5    result = subprocess.run(
6        [sys.executable, "child.py", "--name", "Ana"],
7        capture_output=True,
8        text=True,
9        timeout=15,
10        check=True,
11    )
12    print(result.stdout)
13except subprocess.TimeoutExpired:
14    print("child process timed out")
15except subprocess.CalledProcessError as exc:
16    print("child failed with code", exc.returncode)
17    print(exc.stderr)

check=True tells Python to raise an exception on a non-zero exit code. That is often better than manually checking returncode everywhere.

Pass Structured Data Carefully

If the child needs many parameters, command-line flags can become awkward. For moderate payloads, JSON can work.

Parent:

python
1import json
2import subprocess
3import sys
4
5payload = {"batch_id": 101, "items": [1, 2, 3]}
6
7subprocess.run(
8    [sys.executable, "child_json.py", json.dumps(payload)],
9    check=True,
10)

Child:

python
1import json
2import sys
3
4data = json.loads(sys.argv[1])
5print(data["batch_id"], len(data["items"]))

For large or sensitive data, a file, pipe, or environment variable may be better than long command-line arguments that can appear in process listings.

Control the Working Directory and Environment

Do not let the child script depend implicitly on whatever shell state happened to launch the parent.

python
1import os
2import subprocess
3import sys
4
5env = os.environ.copy()
6env["APP_MODE"] = "batch"
7
8subprocess.run(
9    [sys.executable, "child.py", "--name", "Ana"],
10    cwd="/path/to/project",
11    env=env,
12    check=True,
13)

Setting cwd and env explicitly makes the run more reproducible and easier to diagnose.

When You Need Streaming Output

subprocess.run waits for the child to finish. If you want to stream output while it runs, use Popen.

python
1import subprocess
2import sys
3
4with subprocess.Popen(
5    [sys.executable, "child.py", "--name", "Ana"],
6    stdout=subprocess.PIPE,
7    stderr=subprocess.STDOUT,
8    text=True,
9) as process:
10    for line in process.stdout:
11        print("child:", line.rstrip())
12
13    exit_code = process.wait()
14    print("done:", exit_code)

That is useful for long-running tasks where progress output matters.

Common Pitfalls

The most common mistake is building a shell command string manually instead of passing an argument list. Another is using "python" literally instead of sys.executable, which breaks in virtual environments or systems with multiple Python installations. Developers also ignore exit codes, leaving failed child scripts looking successful just because they printed partial output. Finally, passing secrets on the command line can expose them in process listings or logs.

Summary

  • Use subprocess.run with an argument list for safe child-script execution.
  • Use sys.executable so the child runs with the expected Python interpreter.
  • Define the child interface clearly with argparse.
  • Handle non-zero exits and timeouts explicitly.
  • Set working directory and environment deliberately when reproducibility matters.

Related reading
Free course
Beginner
7 lessons
2 hours
Tackling System Design Interview Problems

A short course that equips you with the skills to approach system design interviews methodically.

Start the free course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

All Rights Reserved.