1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103
|
#-----------------------------------------------------------------------------
# Copyright (c) 2024, PyInstaller Development Team.
#
# Distributed under the terms of the GNU General Public License (version 2
# or later) with exception for distributing the bootloader.
#
# The full license is in the file COPYING.txt, distributed with this software.
#
# SPDX-License-Identifier: (GPL-2.0-or-later WITH Bootloader-exception)
#-----------------------------------------------------------------------------
import argparse
import os
import sys
import subprocess
if __name__ == '__main__':
# Argument parser
parser = argparse.ArgumentParser(description="Sub-process environment inheritance test")
subparsers = parser.add_subparsers(dest="process_type", help="Process type.")
parser_parent = subparsers.add_parser("parent", help="Parent process.")
parser_parent.add_argument(
"child_executable",
type=str,
help="Path to executable to spawn as a child process.",
)
parser_parent.add_argument(
"--force-independent",
action="store_true",
help="Spawn the child process as an independent instance.",
)
parser_child = subparsers.add_parser("child", help="Child process.")
parser_child.add_argument(
"mode",
type=str,
choices={"same", "different"},
help="Child mode - whether executable is the same as parent process or not.",
)
parser_child.add_argument(
"parent_app_dir",
type=str,
help="Top-level application directory of the parent process.",
)
args = parser.parse_args()
if args.process_type is None:
# Process type not specified - exit early.
print("Process type not specified.", file=sys.stderr)
elif args.process_type == "parent":
# Parent process.
print("Running as parent process!", file=sys.stderr)
print(f"Child executable: {args.child_executable}", file=sys.stderr)
print(f"Force independent instance: {args.force_independent}", file=sys.stderr)
env = os.environ.copy()
if (
args.child_executable == "sys.executable"
or os.path.realpath(args.child_executable) == os.path.realpath(sys.executable)
):
subprocess_args = [
sys.executable,
"child",
"different" if args.force_independent else "same",
sys._MEIPASS,
]
if args.force_independent:
env["PYINSTALLER_RESET_ENVIRONMENT"] = "1"
else:
subprocess_args = [
args.child_executable,
"child",
"different",
sys._MEIPASS,
]
print(f"Running child process with arguments: {subprocess_args!r}", file=sys.stderr)
subprocess.run(subprocess_args, check=True, env=env)
else:
# Child process.
print("Running as child process!", file=sys.stderr)
print(f"Mode: {args.mode}", file=sys.stderr)
print(f"Our top-level directory: {sys._MEIPASS}", file=sys.stderr)
print(f"Parent top-level directory: {args.parent_app_dir}", file=sys.stderr)
if args.mode == "same":
# Raise error if directories are different.
if sys._MEIPASS != args.parent_app_dir:
raise SystemExit(
f"Expected top-level directory ({sys._MEIPASS}) to be SAME as that of the parent process "
f"({args.parent_app_dir}), but it is not!"
)
else:
# Raise error if directories are the same.
if sys._MEIPASS == args.parent_app_dir:
raise SystemExit(
f"Expected top-level directory ({sys._MEIPASS}) to be DIFFERENT from that of the parent process "
f"({args.parent_app_dir}), but it is not!"
)
|