I have a compiled Fortran program (lets say in ~/codedir
) linked against Intel MKL, which I want to run with a Python script in a certain directory (lets say calculationdir
).
I can navigate to calculationdir
and execute ~/codedir/code
, where code is the name of the executable. Everything works. But if I try to start the code from the below Python script:
import subprocess
command = '~/codedir/code'
with open('job.out', 'a') as f:
process = subprocess.Popen(command.split(), stdout=f, shell=True)
output, error = process.communicate()
I get the following error:
/home/codedir/code: error while loading shared libraries: libmkl_intel_lp64.so.1: cannot open shared object file: No such file or directory
I suspect that this might have something to do with the environment variables. I configured my shell that every time I start a shell, the script setvars.sh
of Intel One API is executed which sets a lot of things. Could it be case that these variable are not set if I use python's subprocess? Do I have to tell subprocess in some way to execute also the setvars-script
?
You seem to be looking for
There is no need to specify
shell=True
and in fact, when you split the command yourself, it's an error to do so on Unix-like platforms. (The semantics are slightly different on Windows, so while it's still an error, the symptoms are negligible.) See also Actual meaning ofshell=True
insubprocess
Plain
split
is wrong because it doesn't know how to cope with backslash escapes and quoting; if your command doesn't currently contain either of those constructs, you can get away with a basic stringsplit
; but the standard library supplies a function which works correctly regardless, and I see no reason not to useshlex.split
here.As the documentation explains, you should prefer
subprocess.run
over plainPopen
when you can, as the latter requires you to copy/paste several lines of boilerplate code, and even then is less robust unless you know exactly what you are doing, probably at the expense of adding even more boilerplate code for error handling etc.Finally, the actual beef: the keyword argument
cwd
allows you to set the working directory of the subprocess.