Reputation: 125
I've got some Python code that needs to call an .sh script that lives in a different directory and pass a couple variables to it. It's in a .py file that's part of a Flask path for an API.
subprocess.call(shlex.split('script_name.sh {} {}'.format(var1,var2)))
It works if I copy the code to a separate .py file and run it directly from a venv when I'm in the directory where the .py file lives AND I include an os.chdir line in that file:
os.chdir('/path/to/sh_script_dir')
OR if I cd into the directory where the .sh script lives and call it directly using
>> python /path/to/py_file.py
In the latter case, the os.chdir is not needed. However, when I call it from Flask (by hitting the API path for it, like a "real" user) I get:
Exception class: builtins.FileNotFoundError
Exception message: [Errno 2] No such file or directory: 'script_name.sh'
This error happens whether I define the absolute path to the script in that line or not.
I think it's because it's ultimatley being called from the main Flask api.py, which is in whatever working directory it's in, and it's ignoring the os.chdir command.
I know there's another way to do this, with "cwd" but I couldn't get it to work. I've tried many variations on the following but nothing works:
subprocess.call(shlex.split('script_name.sh {} {}'.format(var1,var2), cwd = '/path/to/sh_script_dir'))
subprocess.call(shlex.split('script_name.sh {} {}'.format(var1,var2)), cwd = '/path/to/sh_script_dir')
subprocess.call([shlex.split('script_name.sh {} {}'.format(var1,var2))], cwd = '/path/to/sh_script_dir')
subprocess.call([shlex.split('script_name.sh {} {}'.format(var1,var2)], cwd = '/path/to/sh_script_dir'))
Do I need to define the change in working dir one level up, in the Flask route? Side note is that I'm not entirely sure the shlex.split is needed here but it didn't work without it, then it did, so I left it. I can provide more code/info but the problem seems to be very specific to getting this function to run as if the current working directory is where the .sh script lives, not the .py script.
Upvotes: 3
Views: 9496
Reputation: 140286
I'm suspecting that if the ./
isn't passed to subprocess
, on some systems the command may not be found (security issues, .
not in system path)
The other issue could be a wrong directory/command not really in the directory.
Obviously I couldn't test that, but that's a safe way (and with error checking) to execute a command in a directory, so it should fix your issue, or at least pinpoint a path problem:
command_dir = '/path/to/sh_script_dir'
command_file = os.path.join(command_dir,"script_name.sh")
if not os.path.isfile(command_file):
raise Exception("{}: no such file".format(command_file))
subprocess.call([command_file,var1,var2], cwd = command_dir)
shlex.split
when you can pass the list of arguments insteadUpvotes: 5