Benny Akesson Benny Akesson - 5 months ago 26
Linux Question

Cross-platform issue related to escaping characters with Python / Gradle

I am having cross-platform issues when calling a Gradle JavaExec task from Python. One sub-project has an application to generate some output and it accepts command line arguments to do so.

Gradle task:

task run(type: JavaExec) {
main = 'generator.myGenerator'
classpath = sourceSets.main.runtimeClasspath
if (System.getProperty("exec.args") != null) {
args System.getProperty("exec.args").split()
}
}


On the command line, this is run by typing e.g.:

./gradlew run -Dexec.args="--minBound 5 --maxBound 8"


Another sub-project wants to run this generator and steps into the appropriate directory and makes a subprocess call, passing the relevant parameters:

Python code:

args = ('-Dexec.args=\"--minBound\ ' + str(min_bound) +
'\ --maxBound\ ' + str(max_bound) + '\"')


subprocess.check_call(['./gradlew', 'run', args])


This works well under Cygwin, but fails under Ubuntu 16.04 LTS.
The error message is:

:generator:run
maxBound\ is not a recognized option


This error message is generated by the command line parser of the generator. The issue is clearly that the backslash that Cygwin requires to escape the spaces cause problems. Removing the escapes does not seem to fix the problem on Linux and I am not sure what it needs.

I am using Python 3.5.

All in all, I am not sure if this is an issue of escapes in Linux vs. Windows, if it is a Gradle issue, or if it has something to do with Python. Any help would be greatly appreciated.

Answer

After some tinkering, I noticed that by putting all arguments in a list and turning them into a string with

args = '\ '.join(argList) 

would work on Cygwin and

args = ' '.join(argList) 

would work on Linux. However, I did not find a nice platform-independent way for this solution without detecting which OS was being used. Instead, I found a solution based on raw strings that works well on both Cygwin and Linux.

argRaw = r"-Dexec.args= --minBound {} --maxBound {}"
args = argRaw.format(min_bound, max_bound)