diff --git a/payu/fsops.py b/payu/fsops.py index 6560eade..0ff2b286 100644 --- a/payu/fsops.py +++ b/payu/fsops.py @@ -301,6 +301,18 @@ def needs_subprocess_shell(command: str) -> bool: return False +def env_with_python_path(): + """Return a copy of current environment variables with PATH + modified to include the python interpreter""" + # Get the directory of the current Python interpreter + python_dir = os.path.dirname(sys.executable) + + # Add Python interpreter to PATH + env = os.environ.copy() + env["PATH"] = python_dir + os.pathsep + env["PATH"] + return env + + def _run_script(script_cmd: str, control_path: Path) -> None: """Helper recursive function to attempt running a script command. @@ -315,9 +327,11 @@ def _run_script(script_cmd: str, control_path: Path) -> None: # First try to interpret the argument as a full command try: if needs_subprocess_shell(script_cmd): - subprocess.check_call(script_cmd, shell=True) + subprocess.check_call(script_cmd, shell=True, + env=env_with_python_path()) else: - subprocess.check_call(shlex.split(script_cmd)) + subprocess.check_call(shlex.split(script_cmd), + env=env_with_python_path()) print(script_cmd) except FileNotFoundError: diff --git a/test/test_payu.py b/test/test_payu.py index 7ab218cf..a0416b32 100644 --- a/test/test_payu.py +++ b/test/test_payu.py @@ -6,6 +6,7 @@ import shutil import stat import sys +from unittest.mock import patch # Submodules import payu @@ -327,20 +328,22 @@ def test_run_userscript_python_script_with_shebang_header(tmp_path): with open(python_script, 'w') as f: f.writelines([ '#!/usr/bin/env python\n' + 'import sys\n' f"with open('{tmp_path}/output.txt', 'w') as f:\n", - " f.write('Test Python user script with python shebang header')" + " f.write(f'{sys.executable}')" ]) # Make file executable os.chmod(python_script, 0o775) # Test run userscript - payu.fsops.run_script_command('test_script_with_python_shebang.py', - tmp_path) + with patch.dict(os.environ, {'PATH': '/mocked/path'}): + payu.fsops.run_script_command('test_script_with_python_shebang.py', + tmp_path) - # Check script output + # Check script is run with same python executable as caller with open((tmp_path / 'output.txt'), 'r') as f: - assert f.read() == "Test Python user script with python shebang header" + assert sys.executable.startswith(f.read()) def test_run_userscript_bash_script(tmp_path):