Search code examples
pythongradlebuild.gradlegradlew

Why does Gradle task block on executing a Python script that spawns a process?


I encountered an issue running a Python script from a Gradle task.

Short version

Why does a Gradle task that executes a Python script, where the Python scripts spawns a process, seems to block?

Long version

Background information

I created three Python scripts.

  • start.py: Spawns two processes, which are not terminated when the script exits
  • stop.py: Kills the two spawned process
  • test.py: Does a print("Done") (This script was used for debugging purposes.)

Running all three Python scripts locally from my terminal/console performs the expected behavior.

I have a Gradle task that for each of the Python script, where the task calls the Python script. My build.gradle looks like this:

task start (type:Exec) {
    workingDir './mysie'
    commandLine 'python', 'start.py'
}

task stop(type:Exec) {
    workingDir './mydir'
    commandLine 'python', 'stop.py'
}

task testPython(type:Exec) {
    workingDir './mydir'
    commandLine 'python', 'test.py'
}

The problem I'm trying to solve

I'm using the Gradle wrapper executable, and if I execute gradlew testPython, the task runs and I get a BUILD SUCCESSFUL message.

$ /gradlew test
Parallel execution is an incubating feature.
:testPython
Done

BUILD SUCCESSFUL

Total time: 0.888 secs

So this indicates that gradlew can successfully execute a Python script without blocking. However, when I execute gradlew start, which spawns two processes. It's important to not that the Python script spawns the two processes, but does not terminate them. The Gradle task never completes. It appears to be blocked. Here is the output I see:

$ gradlew start
Parallel execution is an incubating feature.
:start
<Insert Python "print" statement that have been flushed here>
> Building 0% > :start

I can see the processes started on my host. Also, before start.py exists, I print("Exiting..."), which is displayed on the console. So I know the Python script executed and completed.

In another terminal, I execute gradle stop, which successfully terminates the processes.

Here's the weird part. After the gradle stop command completes successfully, the gradle start, which was previously blocked, suddenly completes.

My questions

I need to have the start and stop in separate tasks. So my questions are:

  1. Does the content in my build.gradle file look correct?
  2. Why does Gradle block when it executes a Python script that spawns a process?
  3. How can I "unblock" the gradle start task after the Python script spawns the process?

Solution

    1. The content of build.gradle file looks correct. All the tasks are defined correctly.

    2. Because if task is of type Exec it waits till process is finished, then task finishes also. If two separate processes are started from python script being run from Exec task and they're bounded somehow to script which started them (which is bounded to gradle task itself) it all must finish to allow gradle task to finish as well. Have a look at this question for instance.

    3. By writing a custom task which will start the processes in background. See the question linked above.

    Hope this helps. If there's anything unclear, just ask.