Nick Fromage Nick Fromage - 3 months ago 8
Python Question

Python: Process in one Thread stopping a Process in another Thread from finishing

I'd appreciate some help with threading, which I pretty new to.

The example code is not exactly what I’m doing (‘notepad’ and ‘calc’ are just example commands), but a simplified version that shows my problem.

I want to run two seperate threads that each run a different command a number of times. I would like the code to do this:


  1. Start the first instance of ‘notepad’ and ‘calc’ simultaneously
    (which it does)

  2. When I close an instance of ‘notepad’, to open the
    next instance of ‘notepad’.

  3. When I close an instance of ‘calc’, to
    open the next instance of ‘calc’.

  4. [edit] I want the script to wait until both threads have finished, as it needs to do some processing of the output from these.



However, when I close an instance of ‘notepad’, the next instance of ‘notepad’ does not start until I’ve closed the current instance of ‘calc’ and vice versa. With a bit of de-bugging, it looks like the process (from Popen) for the closed instance of 'notepad' doesn't finish until the current 'calc' is closed.

Running Python 2.7 on Windows 7

Example Code:

from subprocess import Popen, PIPE, STDOUT
from threading import Thread

def do_commands(command_list):

for command in command_list:
proc = Popen("cmd.exe", stdin=PIPE, stdout=PIPE, stderr=STDOUT)
stdout_value, stderr_value = proc.communicate(input=command)

# MAIN CODE
A_command_list = ["notepad\n", "notepad\n", "notepad\n" ]
B_command_list = ["calc\n", "calc\n", "calc\n" ]

A_args = [A_command_list]
B_args = [B_command_list]

A_thread = Thread(target=do_commands, args=(A_args))
B_thread = Thread(target=do_commands, args=(B_args))

A_thread.start()
B_thread.start()

A_thread.join()
B_thread.join()


Thanks in advance :-)

Nick

Answer

So the communicate() method is apparently waiting for all processes opened by Popen and named cmd.exe and started at nearly the same time to terminate. Since the cmd.exe that runs calculator starts at nearly the same time as the cmd.exe that runs Notepad, both communicate() calls (one in A_thread and one in B_thread) wait until both processes term. Thus neither for loop advances until both processes term.

Adding a delay between starting the two threads fixes the problem.

So, leaving your original code unchanged and adding

sleep(1)

between the two Thread starts produces the desired behavior.

Comments