Your code as originally posted was legal, because the long string concatenation expression was inside parentheses, and parentheses automatically allow you continue an expression onto the next line:
output = runcommand("'C:Program FilesBrainSuite18adpdp.exe' " + bfcfile +
" --FRT --FRACT --tensor --nii " + dtinii + " -g " + bvalfile +
" -b " + bvecfile)
However, when you take the exact same expression outside of parentheses, it's no longer valid:
command = "'C:Program FilesBrainSuite18adpdp.exe' " + bfcfile +
" --FRT --FRACT --tensor --nii " + dtinii + " -g " + bvalfile +
" -b " + bvecfile
… because now it's three separate expressions, one on each line. And the first one raises a SyntaxError
, because it ends with a +
with no right arguments.
And if you move the hanging +
to the next line, as in your final posted code:
command = "'C:Program FilesBrainSuite18adpdp.exe' " + bfcfile
+ " --FRT --FRACT --tensor --nii " + dtinii + " -g " + bvalfile
+ " -b " + bvecfile
… now it's syntactically valid, but nonsensical—the first line is fine, but the second line is trying to apply the unary +
operator to a string, so you get a TypeError
.
You can fix this by putting the expression back inside parentheses:
command = ("'C:Program FilesBrainSuite18adpdp.exe' " + bfcfile
+ " --FRT --FRACT --tensor --nii " + dtinii + " -g " + bvalfile
+ " -b " + bvecfile)
… or by using backslash continuation:
command = "'C:Program FilesBrainSuite18adpdp.exe' " + bfcfile
+ " --FRT --FRACT --tensor --nii " + dtinii + " -g " + bvalfile
+ " -b " + bvecfile
Although really, even though indentation isn't meaningful to Python inside expressions the way it is in statements, it is meaningful to human readers, so you should try to make it more readable, maybe something like this:
command = (
"'C:Program FilesBrainSuite18adpdp.exe' " + bfcfile
+ " --FRT --FRACT --tensor --nii " + dtinii
+ " -g " + bvalfile
+ " -b " + bvecfile
)
However, the real fix here should be not using string concatenation in the first place. You're not using the shell here, and in fact you're fighting against it, and not entirely successfully. So just use a list of arguments and don't ask for the shell, and now we don't have to worry about quoting or spacing or getting string concatenation right:
command = [
r"C:Program FilesBrainSuite18adpdp.exe", bfcfile,
"--FRT", "--FRACT", "--tensor", "-nii", dtinii,
"-g", bvalfile, "-b", bvecfile
]
And now, call it without shell=True
:
returned_value = subprocess.call(command)
As a side note, notice that I added an r
before the path to the program. A
in a Python string literal doesn't mean a backslash and a letter b, it means a ^H
backspace character. When using Windows pathnames with backslashes as literal values in your source code, always either escape them, or use a raw r
prefix.
Also, I'm not sure why you added the str(…)
calls all over your code to things that are already strings, but… that's never going to help anything, it just makes things harder to read, so I left them out, as in your original version.